Generating sawtooth signal using Arduino

Hi all!

I am currently working on a project where I have to generate a sawtooth signal using arduino uno to use it as an input for a vertical cavity surface emitting laser.

I was able to generate the sawtooth signal using the code below (the frequency is 50 Hz and the period is 20ms). Now I have to make something like resting periods between the peaks so we get a signal in the first 20 ms then no signal for the next 20-30 ms then another signal and so on; I have added a small sketch to make things clearer.

Any idea how to achieve that? Any help is much appreciated!

Thanks :smiley:

int i=0;
int m;    // takes values from vector
int mypwm[]={0,0,0,1,1,1,2,2,3,3,3,4,4,5,5,5,6,6,7,7,7,8,8,9,9,9,10,10,11,11,12,12,12,13,13,14,14,14,15,15,16,16,16,17,17,18,18,18,19,19,19,20,20,21,21,21,22
,22,23,23,23,24,24,25,25,25,26,26,27,27,27,28,28,29,29,29,30,30,31,31,31,32,32,33,33,33,34,34,35,35,35,36,36,37,37,37,38,38,39,39,39,40,40,41,41,41,42,42,43,43
,43,44,44,45,45,45,46,46,47,47,47,48,48,49,49,49,50,50,51,51,51,52,52,53,53,53,54,54,55,55,55,56,56,57,57,57,58,58,59,59,59,60,60,61,61,61,62,62,63,63,63,64,64
,65,65,65,66,66,67,67,67,68,68,69,69,69,70,70,71,71,71,72,72,73,73,73,74,74,75,75,75,76,76,77,77,77,78,78,79,79,79,80,80,81,81,81,82,82,83,83,83,84,84,85,85,85
,86,86,87,87,87,88,88,89,89,89,90,90,91,91,91,92,92,93,93,93,94,94,95,95,95,96,96,97,97,97,98,98,99,99,99,100,100,101,101,101,102,102,103,103,103,104,104,105,105
,105,106,106,107,107,107,108,108,109,109,109,110,110,111,111,111,112,112,113,113,113,114,114,115,115,115,116,116,117,117,117,118,118,119,119,119,120,120,121,121
,121,122,122,123,123,123,124,124,125,125,125,126,126,127,127,127,128,128,129,129,129,130,130,131,131,131,132,132,133,133,133,134,134,135,135,136,136,136,137,137
,138,138,138,139,139,140,140,140,141,141,142,142,142,143,143,144,144,144,145,145,146,146,146,147,147,148,148,148,149,149,150,150,150,151,151,152,152,152,153,153
,154,154,154,155,155,156,156,156,157,157,158,158,158,159,159,160,160,160,161,161,162,162,162,163,163,164,164,164,165,165,166,166,166,167,167,168,168,168,169,169
,170,170,170,171,171,172,172,172,173,173,174,174,174,175,175,176,176,176,177,177,178,178,178,179,179,180,180,180,181,181,182,182,182,183,183,184,184,184,185,185
,186,186,186,187,187,188,188,188,189,189,190,190,190,191,191,192,192,192,193,193,194,194,194,195,195,196,196,196,197,197,198,198,198,199,199,200,200,200,201,201
,202,202,202,203,203,204,204,204,205,205,206,206,206,207,207,208,208,208,209,209,210,210,210,211,211,212,212,212,213,213,214,214,214,215,215,216,216,216,217,217
,218,218,218,219,219,220,220,220,221,221,222,222,222,223,223,224,224,224,225,225,226,226,226,227,227,228,228,228,229,229,230,230,230,231,231,232,232,232,233,233
,234,234,234,235,235,236,236,236,237,237,238,238,238,239,239,240,240,240,241,241,242,242,242,243,243,244,244,244,245,245,246,246,246,247,247,248,248,248,249,249
};



void setup() {
  
Serial.begin(9600);
pinMode(5, OUTPUT);
cli();                             
TCCR0A=0;
TCCR0B=0;
TCNT0=0;
TCCR0A=0b10100001;
TCCR0B=0b00000001;
TCCR1A=0;                          
TCCR1B=0;                       
TCNT1=0;                          
OCR1A=510;                       

TCCR1B=0b00001001;

TIMSK1 |=(1 << OCIE1A);
sei();                           
}
ISR(TIMER1_COMPA_vect){
if(i>(600)){
i=0; 

}
m=mypwm[i];                     
i=i+1; 
OCR0B=m;                      



}
void loop() {
  
}

Unbenannt

do you have a digital to analog converter in your Arduino?

1 Like

I would start with writing a function for the sawtooth signal instead of using an array with predefined values. At a certain point you probably want to modify the shape (e.g., slope, maximum) of the signal.

You could use that same function to control the time between pulses.

1 Like

You could add 600 to 750 zeros to your array of numbers.

2 Likes

Here is a suggestion for such a function.

uint8_t signal(size_t const x, size_t const ramp, uint8_t const maximum) {
  if (x < ramp) {
    return map(x, 0, ramp, 0, maximum);
  }
  return 0;
}

In your ISR you could something like this:

m = signal(i, 50, 250);
i = (i + 1) % 600;

This will give a linearly increasing output between 0 and 49, after which the output is 0.

1 Like

You could always use an op amp or 555 instead

1 Like

I use arduino uno and it does not have a DAC but I can use an external chip if it can help!

I tried to do it but the code will not run since the data section will exceed the available space in board.

Can you please explain how an Op-amp would help?

First, you should change "int mypwm[]" to "byte mypwm[]" to cut the storage in half. None of your values is greater than 255 and you store the value in a one-byte register (OCR0B).

next you can put constant data in PROGMEM (FLASH memory).

byte mypwm[] PROGMEM ={0,0,0,1,1,1,2,2,3,3,3,4,4,5,5,5,6,6,7,7,7,8,8,9,9,9,10,10,11,11,12,12,12,13,13,14,14,14,15,15,16,16,16,17,17,18,18,18,19,19,19,20,20,21,21,21,22

  m = pgm_read_byte(&mypwm[i]);                     
  i = i + 1; 
  OCR0B = m; 
1 Like

That actually worked well! thanks a lot for your help :smile: :v:

Google is your friend for op amp stuff Op amp circuit

Saw tooth generators were used in CRT type tellys and oscilloscopes to drive the spot across the screen and then “ fly” it back to the left side again- Well before Micro’s were invented .
A analog circuit may give a “smoother “ waveform

1 Like

Now it is working! Thank you!! :smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.