![]() |
|
Re: AID: AID Terminal Language Reference (see "notes" below)
From: Stefan Wiechula stfn_aidp
zooid.org
Date: Fri, 25 Jul 2003 17:07:56 -0700
: Sent via the Art Interface Device mailing list: aid@interaccess.org : Use your "Reply All" to reply to the list, "Reply" for private response On Fri, Jul 25, 2003 at 09:31:01AM -0400, B. Bogart wrote: > AID Terminal Language Reference: ... > Notes: > > * Why does PWM has two duty cycles? (This may be normal, I'm not familiar > though) There are two PWM outputs: RC1 (pin 16) and RC2 (pin 17). The duty cycle of these are independantly configurable but the frequency of both is set by timer 2. When we wrote the current PWM code we started with 3 "low level" PWM related functions in aid_lib.c 1. void aid_pwm_init(void) - configures pins 16 and 17 as outputs, enables timer 2 and sets a reasonable value for it's prescaler, and such. 2. void set_pwm_frequency(unsigned int freq) - currently loads the value of "freq" into the PR2 register but should in the future be changed to calculate and load a value into PR2 which will give the requested frequency in Hz or kHz based on the clock rate and timer 2 prescaler value. 3. void set_pwm_duty_cycle(unsigned char addr, unsigned int duty_cycle) - sets the duty cycle of PWM output 1 (pin 16) or 2 (pin 17). "addr" should be 1 or 2 and "duty_cycle" should be no greater than 100. That covers just about everything you can do with the PWM outputs. When it came to deciding on the syntax of a terminal command for PWM output we considered a few different options, including a single argument command to set the frequency of both and a separate two argument command to set the duty cycle of a particular output. We decided at the time to make just one command with 3 arguments for simplicity but it's easily changed if anyone has a better syntax in mind. Currently, if you'd like to adjust the duty cycle of just one output through the terminal while both are running you'll have to include the original duty cycle setting for the other output. If you've forgotten it then you're out of luck! If it turns out that reloading even the same duty cycle values causes the output to glitch then we could either split the command in two or "smarten up" the code such that it will only write to the CCPR?L registers if the new value is different from the current value. There are a few things that could use cleaning up in the PWM code while we're on the topic, including: a. Using all 10 bits of duty cycle resolution. The 8 most significant bits are set in CCPR1L (CCPR2L for channel 2) and the other two are set elsewhere. Currently we set the two LSb to zero in aid_pwm_init and leave them that way. b. Bounds checking on duty cycle in set_pwm_duty_cycle. Most low level functions in aid_lib.c count on being called with valid arguments by the command interpreter. In the future people may wish to use aid_lib for other purposes. c. Bounds checking on frequency in the command interpreter. MAX_PWM_FREQ is defined as 999 in main.c but that value is arbitrary and it would be better to replace it with the actual maximum or remove that check from the command interpreter and change set_pwm to return an error if the actual maximum is exceeded. d. Scaling the "freq" argument of set_pwm_frequency. Currently that function takes an unsigned integer, limits the value to [0,255] and sets the PWM time period (1/frequency) proportional to that value. The calculation to use "freq" as frequency instead of as time period is in the comments of aid_lib.c but has not been implemented yet. That last point is certainly the most important since it means the "p" terminal command does something very different from what one would expect it to do. > * Is the range of return values from AtoD 0-1023? Yes, the ADC has 10 bits of resolution, 8 in one register and 2 bits as part of another. The registers are called ADRESH and ADRESL. Figure 11-4 (page 116) in the 16F877 datasheet shows how to configure which register holds the 8 bits and which supplies just 2. I think we are using this correctly as we set ADFM = 1 near the top of get_ad and then, after a conversion, do: result = ADRESH; result = result << 8 | ADRESL; to get 10 bits worth of data (2 MSb from ADRESH, 8 LSb from ADRESL) into "result" which is an unsigned int (16 bits wide). Cheers, Stefan. : messages saved at http://www.interaccess.org/aid/list : unsubscribe/help requests to mailto:Majordomo@interaccess.org