Output 0-10V with Arduino (Bit-bang MCP4922 DAC and amplify with TLC272)

Output 0-10V with Arduino (Bit-bang MCP4922 DAC and amplify with TLC272)

Many industrial devices need 0-10 V control signal, to perform some task. For example, a valve actuator will close fully if you send it 0 V and open fully, if you give it 10 V. And everything in between.

How can we send 0-10 V signal from an Arduino? This video is about getting 0-10 V signal out of Arduino with the help of integrated circuits.

// Based on tutorial here: https://circuitdigest.com/article/introduction-to-bit-banging-spi-communication-in-arduino-via-bit-banging

/*
 * This example focuses on a specific case of SPI communication, 
 * where we can use any pin on the Arduino to 
 * communicate with the peripheral device. 
 * In this case that's a DAC MCP4922.
*/

// First we define the constants
const int SSPin = 4;
const int SCKPin = 3;
// const int MISOPin = 9; // Not needed for DAC
const int MOSIPin = 2;

// byte slaveData = 0; // Data received by the slave (device), 
// but not needed in the MCP4922 example
int x;

void setup() {
  pinMode(SSPin, OUTPUT);
  pinMode(SCKPin, OUTPUT);
  // pinMode(MISOPin, INPUT); Not needed for MCP4922 DAC
  pinMode(MOSIPin, OUTPUT);
  digitalWrite(SSPin, HIGH); // Just in case, set it "high" initially...
//  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  // Activate DAC
  digitalWrite(SSPin, LOW);
  x = setDac(1024*4 - 1, 0);

  // Deactivate DAC
    digitalWrite(SSPin, HIGH);
    delay(4);
}

unsigned long setDac(unsigned long value, int channel){ // This function transmits data via bitbanging to the DAC
  
  // byte _receive = 0; We are not receiving anything in the MCP4922 example
    unsigned long dacRegister = 0b0011000000000000; // the first nibble (4 bits) of the register is the definition of the: 1st: channel output (A-0, B-1), 2nd: Buffer (check datasheet, default-0), 3rd: Gain (1x-1, 2x-0), 4th: shutdown (active-1. inactive-0), p. 24

    // Set the channel
    switch(channel){
      case 0: // Channel A;
        dacRegister &= ~(1 << 15);
      break;

      case 1: // Channel B;
        dacRegister |= (1 << 15);
      break;
    }
    
    // Write value to the two bytes to be sent to the DAC
    unsigned long dacSendBytes = dacRegister | value;

    // Start bit-banging
    for(int i = 0; i < 16; i++){
      digitalWrite(MOSIPin, bitRead(dacSendBytes, 15-i));
      delay(2);
      digitalWrite(SCKPin, HIGH);
      delay(2); // Maybe needed.
      digitalWrite(SCKPin, LOW);
    }
}