Sawtooth/ramp wave generator using arduino uno

He was clear about the delays. Are they in the loop() code?

"With delays of 2000ms and 7000ms in zonedro's original (flawed) sketch, the frequency can't be very high."

My issue is that you continue to defend posting falsehoods,

I have bought audio-quality op-amps before. Couldn't one of those boost 3V to 5V?

no problem! hopefully although my code is not for your specific DAC it will give you some ideas!
I have an MCP4725 DAC somewhere about and will try your code

just to check you are running on a UNO
what exactly is the sequence of events?
e.g. generates

  1. a ramp(1 second)/plateau(3 seconds)
  2. delay 7 seconds
  3. ramp(1second)/plateau(3seconds)
  4. delay 30 seconds
    then repeats from 1

could you clarify the above? e.g. with a diagram?

version of post 58 code running on UNO with a MCP4725 DAC
the UNO/MCP4725 is slower than the ESP32 therefore timer interrupts are reduced from 1000/sec to 100/sec with corresponding reduction in the ramp array size from 1000 to 100, e.g.

// UNO driving a MCP4725 DAC
// DAQ using  timer interrupts 100times/second to
// generate 1 second ramp then 3 second HIGH plateau then 7 seconds LOW
// then     1 second ramp then 3 second HIGH plateau then 20 seconds LOW
// then repeat

// see https://forum.arduino.cc/t/sawtooth-ramp-wave-generator-using-arduino-uno/1148037/67

#include <Wire.h>
#include <MCP4725.h>
#include <TimerOne.h>

MCP4725 MCP(0x60);  // MCP4725 address

#define PULSE 8     // pulse output pin

// Sine LookUpTable & Index Variable
volatile int SampleIdx = 0;
uint8_t lookupTable1[100];

// generate 1 second ramp then 3 second HIGH plateau then 7 seconds LOW
// then     1 second ramp then 3 second HIGH plateau then 20 seconds LOW
enum states { STOP,
              RAMP1,
              PLATEAU1,
              ZERO7SEC,
              RAMP2,
              PLATEAU2,
              ZERO30SEC };

volatile int state = STOP, stimer = 0, counter = 0;
void TIMER_ISR() {
  interrupts();   // enable interrupts for Wire
  switch (state) {
    case RAMP1:  // ramp state
    case RAMP2:
      MCP.setValue(40 * lookupTable1[SampleIdx++]);
      if (SampleIdx == 99)  digitalWrite(PULSE,HIGH);   // pulse HIGH 
      if (SampleIdx == 100) {    // if ramp complete
        SampleIdx = 0;           // reset index
        digitalWrite(PULSE,LOW);   // pulse LOW
        //MCP.setValue(10 * 200);  // next state is high
        stimer = 300;           // plateau timer
        switch (state) {
          case RAMP1: state = PLATEAU1; break;  // ramp finished next plateau
          case RAMP2: state = PLATEAU2; break;  // ramp finished next plateau
        }
      }
      break;
    case PLATEAU1:  // plateau state
    case PLATEAU2:  // plateau state
      // analogWrite(DAC0, 200);  // is high
      if (--stimer) break;  // plateau not finished?
      MCP.setValue(0);      // next state is LOW
      switch (state) {
        case PLATEAU1:
          state = ZERO7SEC;
          stimer = 700;
          break;
        case PLATEAU2:
          state = ZERO30SEC;
          stimer = 2000;
          break;
      }
      break;
    case ZERO7SEC:   // zero state
    case ZERO30SEC:  // zero state
      //analogWrite(DAC0, 0);  // is LOW
      if (--stimer) break;  // zero not finished
      switch (state) {
        case ZERO7SEC: state = RAMP2; break;   // next state is ramp
        case ZERO30SEC: state = RAMP1; break;  // next state is ramp
      }
      break;
  }
  counter++;
}

void setup() {
  Serial.begin(115200);
  pinMode(PULSE,OUTPUT); 
  Serial.println("Arduino UNO timer ramp then plateau generator ");
  // call timer handler every 1000 microseconds
  MCP.begin();
  Wire.setClock(800000l);
  Timer1.initialize(10000l);  //Initialize timer with 10 mSec second period
  Timer1.attachInterrupt(TIMER_ISR);
  for (int i = 0, dac = 0; i < 100; i++)  // setup ramp
    lookupTable1[i] = i;
  MCP.setValue(0);  // is LOW
  Serial.println("hit key to start sequence?");
  while (!Serial.available()) delay(10);
  state = RAMP1;  // initial state
}

void loop() {
  static long timer1 = millis();
  if (millis() - timer1 >= 1000) {
    Serial.print("Counter ");
    Serial.print(counter);
    Serial.print(" state  ");
    Serial.println(state);
    timer1 = millis();
    counter = 0;
  }
}

overall generated signal
image

first ramp/plateau showing pulse at end of ramp
image

zoom in to show pulse timing
image

timer1 += 1000; // because millis() - timer1 >= 1000 adds all > 1000!

every time it is more advances the base while += 1000 corrects for late

Robin2 showed us that.

1 Like

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