| Multiple PWM Channels Example Last Modified: 2006-11-06 | | |
| Acroname Robotics | |||
| Introduction In this example, a BrainStem GP 1.0 outputs four 100Hz PWM signals on digital IO pins 0, 1, 2, and 3. This is a variation of the previous Low-Frequency PWM example. It uses simpler reflexes. Each PWM reflex has a main timer loop with a period of 10ms. A second timer controls how long the output is turned on during one PWM cycle, from 0.1ms to 9.9ms in 0.1ms increments. The yields a duty cycle range of 1% to 99% in 1% increments. A scratch pad byte stores the current duty cycle setting. A TEA program or command may set the duty cycle for each PWM output by writing to the scratch pad byte. Once started, the four reflexes that produce PWM on digital pins 0, 1, 2, and 3 run continually. Source Code - Reflex Routine Each PWM reflex must be initialized by configuring its digital IO pin to be an output, setting its duty cycle in the scratch pad to a proper value (1-99), and starting its timer.
Since the reflex timers use 2-byte time settings, each duty cycle setting must be stored in two bytes. Valid duty cycle settings are 1-99, it is sufficient to set the low byte of the timer setting in order to change the duty cycle. Illegal duty cycles will generate error messages. Timers 16-19 are the main timers for the four PWM outputs. Timers 21-24 control how long each output is high during a PWM cycle. Each PWM reflex can be stopped by killing its main timer. Each PWM relfex can be restarted by setting its main timer. (See the cmdTMR_SET documentation for more info about starting and stopping timers.) The reflex source code consists of two files. The first file has defined values that determine what IO the reflexes will use. This file may be included in a TEA program. The reflex code has commands and vectors for four PWM loops. A user can delete unwanted loops if necessary. /* filename: qpwmdef.tea */
#define thisMODULE 2
#define msgON1A 1
#define msgON2A 2
#define msgON3A 3
#define msgON4A 4
#define msgOFF1A 5
#define msgOFF2A 6
#define msgOFF3A 7
#define msgOFF4A 8
#define msgTON1A 9
#define msgTON2A 10
#define msgTON3A 11
#define msgTON4A 12
#define msgPWMGO1 13
#define msgPWMGO2 14
#define msgPWMGO3 15
#define msgPWMGO4 16
#define doutPWM1A 0
#define doutPWM2A 1
#define doutPWM3A 2
#define doutPWM4A 3
#define pwmPADTMR1 0
#define pwmPADTMR2 2
#define pwmPADTMR3 4
#define pwmPADTMR4 6
#define pwmPERIODH 0
#define pwmPERIODL 100
The second file is the leaf file that defines the reflexes. The reflexes can be compiled by entering leaf "qpwm" from the Console. They can be loaded by entering batch "qpwm.bag" from the Console. /* filename: qpwm.leaf */
#include <aCmd.tea>
#include <aGarciaDefs.tea>
#include <aGPReflexes.tea>
#include <aMotoReflexes.tea>
/* user defined macros and values */
#include "qpwmdef.tea"
/************* BEGIN REFLEX *************/
module[thisMODULE] {
/************* REFLEX MESSAGES *************/
message[msgON1A] {
thisMODULE, cmdDIG_IO, doutPWM1A, 1
}
message[msgON2A] {
thisMODULE, cmdDIG_IO, doutPWM2A, 1
}
message[msgON3A] {
thisMODULE, cmdDIG_IO, doutPWM3A, 1
}
message[msgON4A] {
thisMODULE, cmdDIG_IO, doutPWM4A, 1
}
message[msgOFF1A] {
thisMODULE, cmdDIG_IO, doutPWM1A, 0
}
message[msgOFF2A] {
thisMODULE, cmdDIG_IO, doutPWM2A, 0
}
message[msgOFF3A] {
thisMODULE, cmdDIG_IO, doutPWM3A, 0
}
message[msgOFF4A] {
thisMODULE, cmdDIG_IO, doutPWM4A, 0
}
message[msgPWMGO1] {
thisMODULE, cmdTMR_SET, 16, pwmPERIODH, pwmPERIODL
}
message[msgPWMGO2] {
thisMODULE, cmdTMR_SET, 17, pwmPERIODH, pwmPERIODL
}
message[msgPWMGO3] {
thisMODULE, cmdTMR_SET, 18, pwmPERIODH, pwmPERIODL
}
message[msgPWMGO4] {
thisMODULE, cmdTMR_SET, 19, pwmPERIODH, pwmPERIODL
}
message[msgTON1A] {
thisMODULE, cmdPTMR_SET, 21, pwmPADTMR1
}
message[msgTON2A] {
thisMODULE, cmdPTMR_SET, 22, pwmPADTMR2
}
message[msgTON3A] {
thisMODULE, cmdPTMR_SET, 23, pwmPADTMR3
}
message[msgTON4A] {
thisMODULE, cmdPTMR_SET, 24, pwmPADTMR4
}
/************* REFLEX VECTORS *************/
vector[aGP_RFX_TIMER_16] {
msgPWMGO1,
msgTON1A,
msgON1A,
}
vector[aGP_RFX_TIMER_17] {
msgPWMGO2,
msgTON2A,
msgON2A,
}
vector[aGP_RFX_TIMER_18] {
msgPWMGO3,
msgTON3A,
msgON3A,
}
vector[aGP_RFX_TIMER_19] {
msgPWMGO4,
msgTON4A,
msgON4A,
}
vector[aGP_RFX_TIMER_21] {
msgOFF1A
}
vector[aGP_RFX_TIMER_22] {
msgOFF2A
}
vector[aGP_RFX_TIMER_23] {
msgOFF3A
}
vector[aGP_RFX_TIMER_24] {
msgOFF4A
}
}
Activating the Reflexes from the Console Application The following batch file may be used to activate each PWM output. /* configure digital IOs */
2 26 0 0
2 26 1 0
2 26 2 0
2 26 3 0
/* initialize each channel with minimum duty cycle */
2 51 1 1
2 51 3 1
2 51 5 1
2 51 7 1
/* start main timers */
2 39 16 0 100
2 39 17 0 100
2 39 18 0 100
2 39 19 0 100
For testing, an LED on an output pin is a handy indicator since its brightness will vary with duty cycle. After executing the previous batch file, an LED attached to one of the PWM outputs should be glowing very dimly. The following cmdPAD_IO commands will write scratch pad values that set PWM output 0 to a 20% duty cycle, PWM output 1 to a 40% duty cycle, PWM output 2 to a 60% duty cycle, and PWM output 3 to a 80% duty cycle. 2 51 1 20
2 51 3 40
2 51 5 60
2 51 7 80
Revision History:
| ||||
Related Links: Concepts: Description of Pulse Width Modulation (PWM) Related Examples: Generating Low Frequency PWM Signals with a BrainStem GP Example | ||||
| voice: 720-564-0373, email: sales@acroname.com, address: 4822 Sterling Dr., Boulder CO, 80301-2350, privacy © Copyright 1994-2012 Acroname, Inc., Boulder, Colorado. All rights reserved. |