Go Down

Topic: best solution for 12 analog outputs (5 bits) (Read 3701 times) previous topic - next topic

dhenry

Quick note: not sure how you operated the output pins in the isr. You should not use digitalWrite() there, unless digitalWrite() is not used anywhere else.

I operated on the port to avoid that problem.

#31
Oct 19, 2012, 04:31 pm Last Edit: Oct 19, 2012, 04:35 pm by Oldchatterman Reason: 1

A 1k resistor is likely too small. I would go with 10k or 100k if possible.



10k or higher is not possible without additional buffering of the output signal, because of the impedance of the load (see circuit)

I use this sketch:
Code: [Select]
//generate multiple ppm output

//pin configuration
#define PWM_PORT1    PORTB
#define PWM_DDR1     DDRB
#define PWM_PORT2    PORTD
#define PWM_DDR2     DDRD
#define PWM0        (1<<0)
#define PWM1        (1<<1)
#define PWM2        (1<<2)
#define PWM3        (1<<3)
#define PWM4        (1<<4)
#define PWM5        (1<<5)
#define PWM6        (1<<2)
#define PWM7        (1<<3)
#define PWM8        (1<<4)
#define PWM9        (1<<5)
#define PWM10       (1<<6)
#define PWM11       (1<<7)

//set pwm duration for each bit
#define PWM_Bit     (PWM_50us)     //duration of 1 bit
//pin configuration

//defining timing constants
#define PWM_ms      (F_CPU / 64 / 1000)  //milli seconds, 64:1 prescaler
#define PWM_1ms     (PWM_ms)
#define PWM_500us   (PWM_1ms / 2)
#define PWM_250us   (PWM_500us / 2)
#define PWM_100us   (PWM_500us / 5)
#define PWM_50us    (PWM_500us / 10)
#define PWM_2ms     (PWM_1ms * 2)
#define PWM_5ms     (PWM_1ms * 5)
#define PWM_10ms    (PWM_1ms * 10)

//duration examples for 12 channels
unsigned char duration[]={
  0,              //expected output: 0 / 31 * 5v
  5,              //expected output: 5 / 31 * 5v
  10,             //expected output: 10 / 31 * 5v
  14,             //expected output: 14 / 31 * 5v
  18,             //expected output: 18 / 31 * 5v
  23,             //expected output: 23 / 31 * 5v
  31,             //expected output: 31 / 31 * 5v
  5,              //expected output: 5 / 31 * 5v
  10,             //expected output: 10 / 31 * 5v
  14,             //expected output: 14 / 31 * 5v
  18,             //expected output: 18 / 31 * 5v
  23};            //expected output: 23 / 31 * 5v
       
 
//tmr1 ctc isr
ISR(TIMER1_COMPA_vect) {
  static unsigned char index = 0;    //index
 
  //update the period
  if (index) OCR1A = OCR1A * 2;
  else OCR1A = PWM_Bit;
 
  //change the pins
  if (duration[0] & (1<<index)) PWM_PORT1 |= PWM0;  //set pwm0
  else PWM_PORT1 &=~PWM0;                        //clear pwm0
 
  if (duration[1] & (1<<index)) PWM_PORT1 |= PWM1;  //set pwm1
  else PWM_PORT1 &=~PWM1;                        //clear pwm1
 
  if (duration[2] & (1<<index)) PWM_PORT1 |= PWM2;  //set pwm2
  else PWM_PORT1 &=~PWM2;                        //clear pwm2
 
  if (duration[3] & (1<<index)) PWM_PORT1 |= PWM3;  //set pwm3
  else PWM_PORT1 &=~PWM3;                        //clear pwm3
 
  if (duration[4] & (1<<index)) PWM_PORT1 |= PWM4;  //set pwm4
  else PWM_PORT1 &=~PWM4;                        //clear pwm4
 
  if (duration[5] & (1<<index)) PWM_PORT1 |= PWM5;  //set pwm5
  else PWM_PORT1 &=~PWM5;                        //clear pwm5
 
  if (duration[6] & (1<<index)) PWM_PORT2 |= PWM6;  //set pwm6
  else PWM_PORT2 &=~PWM6;                        //clear pwm6
 
  if (duration[7] & (1<<index)) PWM_PORT2 |= PWM7;  //set pwm7
  else PWM_PORT2 &=~PWM7;                        //clear pwm7
 
  if (duration[8] & (1<<index)) PWM_PORT2 |= PWM8;  //set pwm8
  else PWM_PORT2 &=~PWM8;                        //clear pwm8
 
  if (duration[9] & (1<<index)) PWM_PORT2 |= PWM9;  //set pwm9
  else PWM_PORT2 &=~PWM9;                        //clear pwm9
 
  if (duration[10] & (1<<index)) PWM_PORT2 |= PWM10;  //set pwm10
  else PWM_PORT2 &=~PWM10;                        //clear pwm10
 
  if (duration[11] & (1<<index)) PWM_PORT2 |= PWM11;  //set pwm11
  else PWM_PORT2 &=~PWM11;                        //clear pwm11
 
  //update index
  index += 1;                                   // incrment index
  if (index == 5) index = 0;                    //wrap around index
}

//set up the timer1, 64:1 prescaler
void tmr1_init(unsigned short period) {
  TCCR1B &=~0x07;    //stop tmr1
 
  //set up tccr1a
  TCCR1A =    (0<<COM1A1) | (0<<COM1A0) |    //com1a10 = 0b00, normal operations
              (0<<COM1B1) | (0<<COM1B0) |    //com1b10 = 0b00, normal operations
              (0<<WGM11) | (0<<WGM10);       //wgm2..0 = 0b0100, top at OCR1A
  TCCR1B =    (0<<ICNC1) | (0<<ICES1) |      //disable input capture noise canceller and input capture edge select
              (0<<WGM13) | (1<<WGM12) |      //wgm3..0 = 0b0100, top at OCR1A
              (0<<CS12) | (1<<CS11) | (1<<CS10); //cs2..0 = 0b0011, 64:1 prescaler
  TCCR1C = 0x00;

  //reset the timer/counter
  TCNT1 = 0x0000;                            //reset the timer
 
  //load the period
  OCR1A = period;

  //reset the flag
  TIFR1 |= (1<<OCF1A);
 
  //enable the interrupt
  TIMSK1 |= (1<<OCIE1A);
}

void setup(void) {
  //initialize the output pins
  PWM_PORT1 |= PWM0 | PWM1 | PWM2 | PWM3 | PWM4 | PWM5 ; //set the pins
  PWM_DDR1  |= PWM0 | PWM1 | PWM2 | PWM3 | PWM4 | PWM5 ; //set up the pins for output
  PWM_PORT2 |= PWM6 | PWM7 | PWM8 | PWM9 | PWM10 | PWM11 ; //set the pins
  PWM_DDR2  |= PWM6 | PWM7 | PWM8 | PWM9 | PWM10 | PWM11 ; //set up the pins for output
 
  //set up the timer
  tmr1_init(PWM_Bit);
 
  //enable interrupt
  sei();
}

void loop(void) {
}

dhenry

Quote
I use this sketch:


That would work.

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy