Pages: 1 2 [3]   Go Down
Author Topic: best solution for 12 analog outputs (5 bits)  (Read 2779 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
//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) {
}


* Capture.PNG (7.69 KB, 472x274 - viewed 11 times.)
« Last Edit: October 19, 2012, 09:35:30 am by Oldchatterman » Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I use this sketch:

That would work.
Logged

Pages: 1 2 [3]   Go Up
Jump to: