Loop development for DAC

Hi everyone!

This is my first post and I'm very new at developing on the Arduino and haven't much experience with C or C++ languages. So please be gentle.

I'm developing a program that makes use of a rotary encoder and the digital outputs. I'm trying to build a system that will supply an analog voltage output via an 8-bit R2R network of resistors that will utilize D2 - D9 on the Arduino Uno. The DAC will supply an analog signal that will (after a few other elements) drive a constant current source.

I cobbled together some code where i use an array of floats to supply all the possible current set points and i was going to trigger a series of IF statements to match the set point and set the appropriate binary bits on D2-D7 for the given current set point. Currently, it is configured to set the current when the button on the encoder is pressed.

The way I'm writing it now seems inefficient so i was looking for guidance. Is there a faster way i could set the digital pins without defining every single current set point for the 8-bit binary sequence? The way it's written now i will have to define the binary output for an additional 30 current set points.

" if (cset == 0.25) { "
digitalWrite(2, HIGH);
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
digitalWrite(7, HIGH);
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);
}


// Rotary Encoder Inputs
#define CLK 13
#define DT 12
#define SW 11

int counter = 0;
int currentStateCLK;
int lastStateCLK;
String currentDir = "";
unsigned long lastButtonPress = 0;
int csele;
float cset;
float cur_opt[] = {0, 0.25, 0.5, 0.75,
                   1, 1.25, 1.5, 1.75,
                   2, 2.25, 2.5, 2.75,
                   3, 3.25, 3.5, 3.75,
                   4, 4.25, 4.5, 4.75,
                   5, 5.25, 5.5, 5.75,
                   6, 6.25, 6.5, 6.75,
                   7, 7.25, 7.5, 7.75, 8
                  };

void setup() {
  //SET R2R BITS
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);

  // Set encoder pins as inputs
  pinMode(CLK, INPUT);
  pinMode(DT, INPUT);
  pinMode(SW, INPUT_PULLUP);
  // Setup Serial Monitor
  Serial.begin(9600);

  // Read the initial state of CLK
  lastStateCLK = digitalRead(CLK);
}

void loop() {

  // Read the current state of CLK
  currentStateCLK = digitalRead(CLK);

  // If last and current state of CLK are different, then pulse occurred
  // React to only 1 state change to avoid double count
  if (currentStateCLK != lastStateCLK  && currentStateCLK == 1) {

    // If the DT state is different than the CLK state then
    // the encoder is rotating CCW so decrement
    if (digitalRead(DT) != currentStateCLK) {
      counter ++;
      currentDir = "CW";
    } else {
      // Encoder is rotating CW so increment
      counter --;
      currentDir = "CCW";
    }
    csele = counter;
    cset = cur_opt[csele];

    if (counter < 0) {
      counter = 0, cset = 0, csele = 0;
    }
    if (counter > 31) {
      counter = 31, cset = 8.00, csele = 32;
      delay (100);
    }

    Serial.print("Direction: ");
    Serial.print(currentDir);
    Serial.print(" | Counter: ");
    Serial.println(counter);
    Serial.print("C_Set:");
    Serial.println(cset);
    Serial.print("Csele:");
    Serial.println(csele);
  }

  // Remember last CLK state
  lastStateCLK = currentStateCLK;

  // Read the button state
  int btnState = digitalRead(SW);
   //Set binary sequence for given current setpoint on button press.
  //If we detect LOW signal, button is pressed
  if (btnState == LOW) {
    //if 50ms have passed since last LOW pulse, it means that the
    //button has been pressed, released and pressed again
    if (millis() - lastButtonPress > 50) {
      Serial.println("Button pressed!");

     //Example: R2R input of "11111111"   
   if  (cset == 0.25) {
        digitalWrite(2, HIGH);
        digitalWrite(3, HIGH);
        digitalWrite(4, HIGH);
        digitalWrite(5, HIGH);
        digitalWrite(6, HIGH);
        digitalWrite(7, HIGH);
        digitalWrite(8, HIGH);
        digitalWrite(9, HIGH);
      }
      if  (cset < 0.25 or cset > 0.25) {
        digitalWrite(2, LOW);
        digitalWrite(3, LOW);
        digitalWrite(4, LOW);
        digitalWrite(5, LOW);
        digitalWrite(6, LOW);
        digitalWrite(7, LOW);
        digitalWrite(8, LOW);
        digitalWrite(9, LOW);
      }
    }

    // Remember last button press event
    lastButtonPress = millis();
  }

  // Put in a slight delay to help debounce the reading
  delay(1);


}

Welcome to the forum

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination

I think a variation of a traditional algorithm for determining the binary value of a number would work. Or is a variation of successive approximation, somewhere between awake and sober here. :expressionless:

Anyway. I scaled the voltage so I could deal with integers throughout.

// https://forum.arduino.cc/t/loop-development-for-dac/967224

float cur_opt[] = {0, 0.25, 0.5, 0.75,
                   1, 1.25, 1.5, 1.75,
                   2, 2.25, 2.5, 2.75,
                   3, 3.25, 3.5, 3.75,
                   4, 4.25, 4.5, 4.75,
                   5, 5.25, 5.5, 5.75,
                   6, 6.25, 6.5, 6.75,
                   7, 7.25, 7.5, 7.75, 8
                  };


void setup() {
  Serial.begin(9600);
  Serial.println("\nHelloWorld!\n");

  for (int ii = 0; ii < 33; ii++) {

    Serial.print("convert "); Serial.println(cur_opt[ii]);
    convert(cur_opt[ii]);

    Serial.println("");
  }
}

void loop() {
}

void convert(float theFloat)
{
  int theValue = 32.0 * theFloat;  // 0 - 7.999 ? not awake yet
  int bitValue = 128;

  for (int bitNumber = 7; bitNumber >= 0; bitNumber--, bitValue >>= 1) {

    if (theValue >= bitValue) {
      theValue -= bitValue;
//      Serial.print("turn on  bit "); Serial.println(bitNumber); 
        Serial.print("1 ");
    }
    else {
//      Serial.print("turn off bit "); Serial.println(bitNumber); 
        Serial.print("0 ");
    }
  }
}

Obvsly, I hope, the bit numbers would index an array of pin numbers for you digitalWrite()s.

Oh, and this was for an 8 bit ladder. You only need the first N bits.

HTH

a7

I can't usually improve on code I write, but this is a good place for direct port manipulation if the output bits were, say 7..2 on an UNO:

// https://forum.arduino.cc/t/loop-development-for-dac/967224

float cur_opt[] = {0, 0.25, 0.5, 0.75,
                   1, 1.25, 1.5, 1.75,
                   2, 2.25, 2.5, 2.75,
                   3, 3.25, 3.5, 3.75,
                   4, 4.25, 4.5, 4.75,
                   5, 5.25, 5.5, 5.75,
                   6, 6.25, 6.5, 6.75,
                   7, 7.25, 7.5, 7.75, 8
                  };


void setup() {
  Serial.begin(9600);
  Serial.println("\nHelloWorld!\n");

  DDRD |= 0b11111100;

  for (int ii = 0; ii < 33; ii++) {

    Serial.print("convert "); Serial.print(cur_opt[ii]);
    byte result = convert(cur_opt[ii]);

    PORTD &= 0b00000011;
    PORTD |= result;

    delay(200);
  }
}

void loop() {
}

byte convert(float theFloat)
{
  int theValue = 32.0 * theFloat;  // 0 - 7.999 ? not awake yet
  int bitValue = 0b10000000;
  byte output = 0;

  for (int bitNumber = 7; bitNumber >= 3; bitNumber--, bitValue >>= 1) {

    if (theValue >= bitValue) {
      theValue -= bitValue;
//      Serial.print("turn on  bit "); Serial.println(bitNumber); 
//        Serial.print("1 ");
        output |= bitValue; 
    }
    else {
//      Serial.print("turn off bit "); Serial.println(bitNumber); 
//        Serial.print("0 ");
    }
  }

  return output;
}

a7

Hi alto777,
Thanks so much for your response and code.

I realize i left out some critical details about my application. So the circuit i will be using functions on a 0-5 V input signal. The total range of the current driver will be from 0-12 A as opposed to the 0-8 Amps i have allotted for in my code. I expect the optical system I'm driving the current on to be unstable at anything beyond 8 Amps so i chose to cap it early in my program to mitigate this. So 5v / 12 A max = ~ 0.415 V/A. Consequently for 8 amps of current i need an analog signal of about 3.33 - 3.5 V.

I'm considering remapping the feedback resistor on the "balancing" op-amp to tune the circuit to function from 0-5 V input @ 0- 8 A but i like the idea of more power rather than less.

Yes i looked into direct port manipulation when i first started this thing because it seemed much easier to store an array of binary numbers rather than call them with an index rather than creating the association later between the set points and the values. Unfortunately, i had an awful time getting them to work and abandoned the technique. IIRC i had different pins turning on than i expected. I was using port D and expected the ports to turn high in the following sequence. B-D0-D1-D2-D3-D4-D5-D6-D7 = 11111111

I was pretty frustrated by the time i was looking at it last time so I'll take another look today as i likely misunderstood something. I just read something about the serial communicator creating issues for D0 and D1 so maybe that was the issue.

EDIT:
I confirmed that direct port manipulation works fine. I even tried it with serial monitor open and still no issues. I'm uncertain what i did wrong before but thanks for the suggestion. This will be a better option than digitalWrite. Thanks again for the suggestion!

Well I can be the first to say that both my versions are extremely stupid.

You could use an external DAC over SPI or I2C, both bus orientated methods well understood and used for this, and inexpensive ICs or modules can be purchased.

If you stick with the R2R ladder for need or desire, you can just multiply the floating voltage value and get the binary representation immediately no algorithm like I had fun with and wasted spent time on. :expressionless:

Direct port manipulation is not hard once it is easy.

Assuming you have an UNO, PORTD bits 7 to 2 are perfectly available, yes don’t use 0 and 1.

I’ll check the 2nd wokwi, I think it has the necessary voodoo.*

Do you need more than 6 bits? The lowest order bits could just be on another port.

Woukd it matter if all 8 bits did not change at the same instant? No matter how, if the bits come from different ports you output will glitch in transition between values.

You could use a Mega and have your own port all to yourself, so to speak. By then maybe the external FAC will be in competition.

After I walk the neighbor’s dog.*

a7

Oh, I just had it working on 0-7. Using this simple example I found online.

// Digital 0~7 set to outputs, then on/off using port manipulation

void setup()
{
  DDRD = B11111111; // set PORTD (digital 7~0) to outputs
}

void loop()
{
  PORTD = B10101010; // digital 4~7 HIGH, digital 3~0 LOW
  delay(4000);
  PORTD = B01010101; // digital 4~7 LOW, digital 3~0 HIGH
  delay(4000);
}


Any reasons other than the serial monitor causing issues to be concerned with? Final version will utilize an I2C LCD for adjustments, interaction and feedback so the serial monitor will not be needed anymore after the debug phase. I can probably get away with 6 bits to control and take the hit on the resolution but i gotta do that math real quick and confirm i can still come close to 1/4 A increments.

I might be able to get away with having slightly different turn on as long as the weightiest of the bits are all on one port. Only concern there would be overshoot from a M[ore]SB turning on before the others turn off.

Regarding the external DAC:

I'll be the first to admit that I'm not an expert in these devices. I'd shy away from I2C as my display will be based on this but this isn't based on anything other than a fear of noise and superstition...

It's funny, the original plan prior to settling on the R2R was actually to get a device like the LTC2644 which will convert a PWM output into an analog signal. I was planning on adjusting Duty Cycle to control current. While shopping for it i found it was sold out damn near everywhere i looked! Considered a low pass filter briefly but was concerned with power stability in the optics. Eventually settled on an R2R due to the simplicity but I'm not particularly attached to the idea but am on a pretty tight timeline. I need to wrap up the base level software development in a week or two so i can start in on refining the circuit from test values from the DAC. I'll research SPI communication

That's a reason to go for it, not to shy away from it! I²C bus is designed to have multiple devices connected.

I like R2R. The external DAC is easy, but woukd mean finding the part and coming to grips with the bus. BTW both SPI and I2C support multiple devices hung on the bus at the same time.

It is inconvenient to use 0 and 1, at the very least it gets in the way of using Serial.print statements for testing and so forth.

Even with an LCD, it can be nice to have/leave Serial.print statements that report program flow. If you don’t have a monitor attached, the characters just go… nowhere.

So since you can tolerate a little low order bits glitch, just put those on 8 and 9, with digitalWrite until you take a few minutes and figure out how to direct manipulate those bits, too, then the glitch will be small and brief.

a7

Why? It will make your code less portable, should you want to move to some other board not based on atmega328.

EDIT: oh, is it because of a desire to have all bits change at the same instant, avoiding any short glitches in the output signal? I guess that's it. You could attach your R2R network to the outputs of a 74hc595. Then the bits would change at the same instant when the latch line is triggered.

Normally I'd agree with you but i got a lot of stuff to develop and a relatively short timeline so I've been gravitating towards the stuff i understand a bit better.

Why not use a processor that has a built in DAC?

So here is it just counting:

// https://forum.arduino.cc/t/loop-development-for-dac/967224

void setup() {
  Serial.begin(9600);
  Serial.println("\nHelloWorld!\n");

  DDRD |= 0b11111100;  // MSBs on 7..2 
  DDRB |= 0b00000011;  // LSBs on 9..8

  byte aByte = 0;

  while (1) {

    myByte(aByte);
    aByte++;

    delay(777);
  }
}

void myByte(byte theByte)
{
// 8 bits to 7 6 5 4 3 2 9 8
  PORTD = (PORTD & 0b00000011) | (theByte & 0b11111100);
  PORTB = (PORTB & 0b11111100) | (theByte & 0b00000011); 
}

void loop() {
}

See it in action

and just multiply your analog voltage 0 - 7.9999 by 32 to get the integer you need.

There will be a very short time between the first 6 MSBs and the last 2 LSBs. The multiplication will truncate the fractional part, you may want to do something a bit <- see what I did there? different when you form the integer.

a7

lol somebody's a Dad!

Looks great!

When doing port manipulation on B are you changing the states of 10, 11, 12 and 13? I'm currently using these ports for my rotary encoder and don't want to change the states of these pins cause they are already doing such a good job.

If so i could always move 8, and 9 to port C and do the same thing on a different letter.

No, I believe I have left the unused bits 0, 1 and 10 and up unused, unchanged, not affected.

So you shoukd be able to use them in any way that you do already.

If not, I’ve made a mistake, perhaps one I can fix but def fixable.

That’s the intent of the masking and & and | operators.

a7

A lot of people misunderstand the R2R ladder when it comes to the resistors. An 8 bit ladder requires the resistors to have a much tighter tolerance than you can buy. While the absolute value of the resistor does not matter they all have to be within 1/256 th of each other, that is 0.39 % tolerance. Otherwise the least significant bits just contribute noise.

The key word here is monotonicity. Monotonic function
This means that the change in the output for an input increase of 1 must produce a change in the output that is greater than you had with the input N-1. In other words each increase in the input must produce an output that is greater or the same as the previous input. It also works the same going down, but if you have it going up it will be fine going down.
The most troublesome transitions are on the wrap round of binary data. For example going from 01111111 to 10000000.

Most sensibly priced resistors are 1% tolerance. So in order to get monotonicity using an R2R ladder the biggest ladder you can simply make is a six section ladder.

The ways round this are to buy a bunch of resistors and measure them and select the ones that are closest together especially for the least significant bits.
Or you could buy a bunch of half value resistors, measure them and find pairs that when placed in series will give you the final value you need.

Or you could buy an R2R resistor ladder pack on a thick film mount, but these might be hard to get hold of.

You could replace each resistor with a 10 turn preset resistor and adjust the value to what ever you want.

Beware there are circuits out there on the net from seemingly respectable people who claim you can get a 16 bit D/A by joining up two 8 D/A ladders, but these people really don't know what they are doing, and they never have precise enough equipment to measure what they have.

So I would shy away from anything other than a 6 bit ladder and go for a real D/A.

Thanks for your response Grumpy_Mike and for the details on True 8 bit R2R.

As an update to this thread i ended up going with an I2C device for the DAC. I purchased the MCP4725 and got it to play nice with my I2C display and am pleased to report i have a functional control system on the Arduino and have moved on to developing my current source circuit. I utilized a rotary encoder for selection and changing of the current via an LCD menu system I'll update this thread when i get home with the details just in hopes it helps somebody else out who has a similar application.

I also wouldn't mind some feedback on the code in it's current form. Code is pretty rough as is and I'm going to need to dig back into it when i add in some current sense and photo-diode feedback systems as well as an enable / disable 5 V digital signal.

Off to the beach just now, but bring it! We take a look.

Good work, BTW.

a7

Thanks man and i appreciate your support Alto

Hope you enjoyed the beach sounds better than my day!

Here's the code, Please let me know your suggestions for improvement. I have more functionality i plan to add in and listed it at the bottom.

//Based on YWROBOT's LiquidCrystal_I2C library, Library version:1.1
//Also based on the Debounce.ino sketch that comes with Arduino IDE
 
#include <Wire.h> // Companion for I2C
#include <LiquidCrystal_I2C.h>  //I2C library for LCD
#include <Adafruit_MCP4725.h> // MCP4725 library from adafruit

// Rotary Encoder Inputs
#define CLK 13
#define DT 12
#define SW 11

// set the LCD address to 0x27 for a 16 chars and 2 line display 
LiquidCrystal_I2C lcd(0x27,16,2);  

//Intialize DAC
Adafruit_MCP4725 MCP4725; 

int C_select; 
int WhichScreen = 1;                 // This variable stores the current Screen number
boolean hasChanged = true;
const int buttonPin = 11;            // the number of the pushbutton pin
int buttonState;                     // the current reading from the input pin
int lastButtonState = LOW;           // the previous reading from the input pin
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers
float I_Act;                         //Will be used as analog read from Current sense resistor.
int counter = 0;
int currentStateCLK;
int lastStateCLK;
String currentDir = "";
unsigned long lastButtonPress = 0;
int csele;
float I_Set;
float I_Set_previous;
float dac_volt;
int dac_ADC;

//Current (A) setpoints array options 
float cur_opt[] = {0, 0.25, 0.5, 0.75,
                   1, 1.25, 1.5, 1.75,
                   2, 2.25, 2.5, 2.75,
                   3, 3.25, 3.5, 3.75,
                   4, 4.25, 4.5, 4.75,
                   5, 5.25, 5.5, 5.75,
                   6, 6.25, 6.5, 6.75,
                   7, 7.25, 7.5, 7.75, 8
                  };

 
void setup()
{
  // intialize MCP4725 DAC
  MCP4725.begin(0x60); 

  //Normalizes I_Set
  I_Set = I_Set_previous;
  
  //0-5 V = 0-8 A. 5/8 = 0.625 V/A
  dac_volt = (0.625*I_Set);
  dac_ADC = (4096/5)*dac_volt;

  // Set encoder pins as inputs
  pinMode(CLK, INPUT);
  pinMode(DT, INPUT);
  pinMode(SW, INPUT_PULLUP);
  
  // Setup Serial Monitor
  Serial.begin(9600);

  // Read the initial state of CLK
  lastStateCLK = digitalRead(CLK);

  // initialize Current set and Current actual
  I_Set = 0;
  I_Act = 1; // Will change into mV / A from current sense resistor.
  
  // initialize the LCD
  lcd.init();
  lcd.backlight();
  pinMode(buttonPin, INPUT);

  //Boot screen (Happens on startup)
  lcd.clear();
  lcd.setCursor(0,0); // Column, line
  lcd.print("LP fiber laser!");
  lcd.setCursor(0,1); // Column, line
  lcd.print("Booting up...");
  delay(3000);
  lcd.clear();
  WhichScreen = 0; 
  }
  
void loop(){

  
  if (hasChanged == true) {
   
  switch(WhichScreen) {
    case 1:
    {
      firstScreen();
    }
      break;
   
    case 2:
      {
        secondScreen();
      }
      break;
    case 0:
      {
       
      }
      break;
    }
}
 
    //-------------------------------
    // BEGIN of the switch debouncing code
    int reading = digitalRead(buttonPin);
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }
 
if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
 
    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;
 
      // only toggle the LED if the new button state is HIGH
      if (buttonState == HIGH) {
        hasChanged = true;
        WhichScreen++;   
      }
    } else {
      hasChanged = false;
    }
  }
  lastButtonState = reading;
  // END of the switch Debouncing code
  // --------------------------------------
  if (WhichScreen > 2){
    WhichScreen = 1;
  }
}
 
void firstScreen()    //Main function. Displays current set /  current actual. Click rotary to set current
  {
    lcd.clear();
    lcd.setCursor(0,0); // Column, line
    lcd.print(" I_Set: ");
    lcd.setCursor(10,0);
    lcd.print(I_Set);
    lcd.setCursor(0,1);
    lcd.print(" I_Act: ");
    lcd.setCursor(10,1);
    lcd.print(I_Act);
  }

//Second screen = Adjust current (A) function. Displays current set / current actual. 
//Spin to Adjust - auto updates. Click to confrim. MCP only chages on click.

void secondScreen()   
  {
    lcd.clear();
    lcd.setCursor(0,0); // Column, line
    lcd.print("  Set current:");
    lcd.setCursor(0,1); // Column, line
    lcd.print(" I_Set: ");
    lcd.setCursor(10,1);
    lcd.print(I_Set); 
while (WhichScreen = 1) {                             //While loop to display current set as adjusted. Prevents MCP from setting voltage until break
  // Read the current state of CLK
  currentStateCLK = digitalRead(CLK);

  // If last and current state of CLK are different, then pulse occurred
  // React to only 1 state change to avoid double count
  if (currentStateCLK != lastStateCLK  && currentStateCLK == 1) {

    // If the DT state is different than the CLK state then
    // the encoder is rotating CCW so decrement
    if (digitalRead(DT) != currentStateCLK) {
      counter ++;
      currentDir = "CW";
    } else {
      
      // Encoder is rotating CW so increment
      counter --;
      currentDir = "CCW";
    }
    //Perhaps unecessary
    csele = counter;
    
    //Current select Array
    I_Set = cur_opt[csele];
    
    //0-8 A I set = 0-5 V V_in.
    dac_volt = (0.625)*I_Set;
    //ADC to volts
    dac_ADC = (4096/5)*dac_volt;

    if (counter < 0) {
      counter = 0, I_Set = 0, csele = 0;
    }
    if (counter > 31) {
      counter = 31, I_Set = 8.00, csele = 32;
      delay (100);
    }

//Serial debug 
    Serial.println("Direction: ");
    Serial.print(currentDir);
    Serial.print(" | Counter: ");
    Serial.println(counter);
    Serial.print("I_Set:");
    Serial.println(I_Set);
    Serial.print("Csele:");
    Serial.println(csele);
    Serial.println("dac_volt");
    Serial.println((dac_volt));
    Serial.println("dac_ADC");
    Serial.println((dac_ADC));
  
//update current select    
    lcd.clear();
    lcd.setCursor(0,0); // Column, line
    lcd.print("  Set current:");
    lcd.setCursor(0,1); // Column, line
    lcd.print(" I_Set: ");
    lcd.setCursor(10,1);
    lcd.print(I_Set); 
  }
  // Remember last CLK state
  lastStateCLK = currentStateCLK;

  // Read the button state
  int btnState = digitalRead(SW);

  //If we detect LOW signal, button is pressed
  if (btnState == LOW) {
    //if 50ms have passed since last LOW pulse, it means that the
    //button has been pressed, released and pressed again
    
    //intiate check for MCP coltage set.
    if (millis() - lastButtonPress > 50) {
      Serial.println("Button pressed!");
      delay(100);
      
      if  (I_Set_previous != I_Set) {
      MCP4725.setVoltage(dac_ADC, false);
      I_Set_previous = I_Set;
      WhichScreen = 1;
      //Serial debug for loop.
      Serial.println("End While");
      }
    // Remember last button press event
    lastButtonPress = millis();
   if (WhichScreen = 1){  //if statement may be unecessary. Break on click instead.
    break;
   }
  }
  // Put in a slight delay to help debounce the reading
  delay(1);
  }
  }
      WhichScreen = 1;
  }

Functionality to add:

  • Add in feedback for I_Act. (Just coded to 1) - Will be an analog read from a current sense resistor. (x # of mV = x # of Amps). needs to function in all screens

  • Feedback from Photodiode. Analog read? Needs to be an "interrupt" function i believe to disable the laser in the event no light is seen at the output. I'm building in an extra MOSFET in the current driver that will basically function as an interrupt on the analog set line in the electronics. (eg. LOW = laser off regardless of current setpoint in software.)
    Also needs to always be polling in the background to check for failure

  • Add in Digital output to supply the enable signal (DigitalWrite). Can be driven low to shut down the system.