Help to convert code to sub routine

The code below is a simple one to get a ramp voltage output from a DAC once the user enters the Start Time , End Time, Start Voltage , End Voltage.

Since I will be using this very often in a code with different ramp rates, I want to be able to convert this to a sub routine with the four parameters as arguments to the function.

I think I need to have a function which does all the calculations once and runs the iterations from the next call onwards. Any other better idea ?? Thanks

#include <Wire.h>
#include <Adafruit_MCP4725.h>

Adafruit_MCP4725 dac;

// Set this value to 9, 8, 7, 6 or 5 to adjust the resolution
#define DAC_RESOLUTION    (9)

float rampStartVal = 1 , rampEndVal = 2;
float rampStartSec = 0, rampEndSec = 5;
uint16_t rampVal ;
float rampCount;
float rampValTotal;
uint16_t perCountRampVal;
uint16_t dacStartCode;
uint16_t dacEndCode;

unsigned long dacUpdateInterval = 50, dacUpdateMs = millis();

void setup(void) {
  Serial.begin(9600);
  // For Adafruit MCP4725A1 the address is 0x62 (default) or 0x63 (ADDR pin tied to VCC)
  // For MCP4725A0 the address is 0x60 or 0x61
  // For MCP4725A2 the address is 0x64 or 0x65
  dac.begin(0x62);
 
  dac.setVoltage(0, false);                             // Initialize the DAC output to zero
  rampCount = ((rampEndSec - rampStartSec ) * 1000) / dacUpdateInterval; // Find the number of iterations required
 
  rampValTotal = ( rampEndVal - rampStartVal ) * 1000;  // Find the absolute value of voltage increase
 
  perCountRampVal = (( rampValTotal / rampCount ) * 4095) / 5000; // Find the per iteration voltage increment
  
  dacStartCode = rampStartVal * 1000 * 4095 / 5000; // Start count for DAC

  dacEndCode = rampEndVal * 1000 * 4095 / 5000;     // End count for DAC
  
  rampVal = dacStartCode;                           // Preload the DAC with start count. 
}

void loop(void) {

  if ( millis() - dacUpdateMs > dacUpdateInterval ) {
    dacUpdateMs = millis();
    if ( rampVal < dacEndCode ) {
      rampVal =  perCountRampVal + rampVal;
      dac.setVoltage(rampVal, false);
    }
  }
}

you could abstract that into a class offering a ramp-up or ramp-down capability.

with the use of a timer the class could auto-trigger or you could have a class method that you call from the loop "often enough" which handles all the instances and see if a step needs to be taken

an example in the FadeLed library or the Button check in easyRun

1 Like

A function passed 4 parameters sounds like the right idea but if the variables are declared global there is no need to pass them. Both ways have advantages and disadvantages

In the sketch that you posted all of the variables are global so you could just put any code in a function and call it, like this

#include <Wire.h>
#include <Adafruit_MCP4725.h>

Adafruit_MCP4725 dac;

// Set this value to 9, 8, 7, 6 or 5 to adjust the resolution
#define DAC_RESOLUTION    (9)

float rampStartVal = 1 , rampEndVal = 2;
float rampStartSec = 0, rampEndSec = 5;
uint16_t rampVal ;
float rampCount;
float rampValTotal;
uint16_t perCountRampVal;
uint16_t dacStartCode;
uint16_t dacEndCode;

unsigned long dacUpdateInterval = 50, dacUpdateMs = millis();

void setup(void)
{
  Serial.begin(9600);
  // For Adafruit MCP4725A1 the address is 0x62 (default) or 0x63 (ADDR pin tied to VCC)
  // For MCP4725A0 the address is 0x60 or 0x61
  // For MCP4725A2 the address is 0x64 or 0x65
  dac.begin(0x62);
  dac.setVoltage(0, false);                             // Initialize the DAC output to zero
  calculate();
}

void loop(void)
{
  if ( millis() - dacUpdateMs > dacUpdateInterval )
  {
    dacUpdateMs = millis();
    if ( rampVal < dacEndCode )
    {
      rampVal =  perCountRampVal + rampVal;
      dac.setVoltage(rampVal, false);
    }
  }
}

void calculate()
{
  rampCount = ((rampEndSec - rampStartSec ) * 1000) / dacUpdateInterval; // Find the number of iterations required
  rampValTotal = ( rampEndVal - rampStartVal ) * 1000;  // Find the absolute value of voltage increase
  perCountRampVal = (( rampValTotal / rampCount ) * 4095) / 5000; // Find the per iteration voltage increment
  dacStartCode = rampStartVal * 1000 * 4095 / 5000; // Start count for DAC
  dacEndCode = rampEndVal * 1000 * 4095 / 5000;     // End count for DAC
  rampVal = dacStartCode;                           // Preload the DAC with start count.
}
2 Likes

How complex is this going to become? Could there be multiple DACs eventually? Do you need to worry about overlap.

I was going to suggest putting your parameters in a struct, including time in millis when the ramp started and pass it to your function by reference. I like @J-M-L's solution better.

I am one of those guys who miss a beat when someone says class :wink:

Ok let me run through the example you cited. Thanks !!

Okay I tried my own way and came up with this. Not too bad I think. I now only have to figure out a way to know when the ramp has reached the required level. Maybe I will need to work out something within the function and pass the status as a boolean ?

#include <Wire.h>
#include <Adafruit_MCP4725.h>

Adafruit_MCP4725 dac;

// Set this value to 9, 8, 7, 6 or 5 to adjust the resolution
#define DAC_RESOLUTION    (9)

unsigned long dacUpdateInterval = 50, dacUpdateMs = millis();

void setup(void) {
  Serial.begin(9600);
  // For Adafruit MCP4725A1 the address is 0x62 (default) or 0x63 (ADDR pin tied to VCC)
  // For MCP4725A0 the address is 0x60 or 0x61
  // For MCP4725A2 the address is 0x64 or 0x65
  dac.begin(0x62);
  dac.setVoltage(0, false);                             // Initialize the DAC output to zero
}

//=========================

void loop(void) {

  rampUpVoltage( 0.5, 4.5, 0, 5);

}

//=========================

void rampUpVoltage ( float rampStartVal, float rampEndVal, float rampStartSec, float rampEndSec) {

  float rampCount;
  float rampValTotal;
  float perCountRampVal;
  float dacStartCode;
  float dacEndCode;

  rampCount = ((rampEndSec - rampStartSec ) * 1000) / dacUpdateInterval; // Find the number of iterations required
  rampValTotal = ( rampEndVal - rampStartVal ) * 1000;                   // Find the absolute value of voltage increase
  perCountRampVal = ( rampValTotal / rampCount ) * 4095 / 5000;          // Find the per iteration voltage increment
  dacStartCode = rampStartVal * 1000 * 4095 / 5000;                      // Start count for DAC
  dacEndCode = rampEndVal * 1000 * 4095 / 5000;                          // End count for DAC

  uint16_t static rampVal = dacStartCode  ;

  if ( millis() - dacUpdateMs > dacUpdateInterval ) {
    dacUpdateMs = millis();
    if ( rampVal <= dacEndCode ) {
      rampVal +=  perCountRampVal ;
      dac.setVoltage(uint16_t(rampVal), false);
    }
  }
}

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