Skip to content

Instantly share code, notes, and snippets.

@Electronza
Last active March 22, 2021 04:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Electronza/470d485ba449b8337a338c090ccec7aa to your computer and use it in GitHub Desktop.
Save Electronza/470d485ba449b8337a338c090ccec7aa to your computer and use it in GitHub Desktop.
VREG Click: adjustable power supply with Arduino Uno
# Project page
# https://medium.com/electronza/vreg-click-adjustable-power-supply-with-arduino-uno-2c61422e17bd
#include <SPI.h>
// PIN definitions for VREG click
// uses mikroBUS socket #1
#define DAC_CS 10 // chip select for MCP4921 DAC
#define ADC_CS A0 // chip select for MCP3204 ADC
#define OUT_PIN 6 // output on/off
// Vreg Click uses SPI communication (pins 11, 12, 13)
// Used to read voltages
float Vin;
float Vsense;
float Vout;
unsigned int Vtmp; // stores ADC results
int incomingByte = -1; // stores incoming serial data
// Variables used for DAC
int setDAC = 909; // start with 3.3V output
int maxDAC = 3090;
int minDAC = 227;
// Preset voltages. Be sure to give values in the {minDAC, ... , maxDAC] interval
int vset1 = 600; // 3.3V
int vset2 = 909; // 5V
int vset3 = 1636; // 9V
int vset4 = 2181; // 12V
int vset5 = 2727; // 15V
// Output status
bool output_status = false;
// Used to update the serial output
// Take a look at "Blink without Delay" example. It helps!
unsigned long previousMillis = 0; // will store last update time
const long interval = 500; // update interval
void setup() {
// Set required pins as output
pinMode(DAC_CS, OUTPUT);
pinMode(ADC_CS, OUTPUT);
pinMode(OUT_PIN, OUTPUT);
// set CD pins on HIGH
digitalWrite(DAC_CS, HIGH);
digitalWrite(ADC_CS, HIGH);;
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
SPI.begin();
outputOFF(); // output is off when we start
DAC_Output(setDAC); // start with 3.3V output
// Now some info
Serial.println ("VREG Click Arduino adjustable power supply");
Serial.println (" ");
Serial.println ("Send + or = to increase voltage");
Serial.println ("Send - or _ to decrease voltage");
Serial.println ("Send 0 or ) for a fine increase of voltage");
Serial.println ("Send 9 or ( for a fine decrease of voltage");
Serial.println ("Send 1 for 3.3V output");
Serial.println ("Send 2 for 5V output");
Serial.println ("Send 3 for 9V output");
Serial.println ("Send 4 for 12V output");
Serial.println ("Send 5 for 15V output");
Serial.println ("Send SPACE to turn output ON or OFF");
Serial.println (" ");
Serial.println ("Send any key to start");
Serial.println (" ");
while(Serial.available() == 0){}
}
void loop() {
// Receive data from terminal
if (Serial.available()) {
incomingByte = Serial.read();
// read the incoming byte:
if (incomingByte >= 0) // incomingByte = -1 if no data is received
{
// Are we increasing the voltage?
if ((incomingByte == 0x2B) | (incomingByte == 0x3D)) // 0x2B = "+", 0x3D = "="
{
setDAC = setDAC + 90; // increase voltage
}
if ((incomingByte == 0x30) | (incomingByte == 0x29)) // 0x30 = "0", 0x29 = ")"
{
setDAC = setDAC + 1; // fine increase voltage
}
// check for max value
if (setDAC > maxDAC)
{
setDAC = maxDAC;
}
// Are we decreasing the voltage?
if ((incomingByte == 0x2D) | (incomingByte == 0x5F)) // 0x2D = "-", 0x5F = "_"
{
setDAC = setDAC - 90; // decrease voltage
}
if ((incomingByte == 0x39) | (incomingByte == 0x28)) // 0x39 = "9", 0x28 = "("
{
setDAC = setDAC - 1; // fine decrease voltage
}
// check for min value
if (setDAC < minDAC)
{
setDAC = minDAC;
}
// Preset values
if ((incomingByte == 0x31) | (incomingByte == 0x21)) // 0x31 = "1", 0x21 = "!"
{
setDAC = vset1;
}
if ((incomingByte == 0x32) | (incomingByte == 0x40)) // 0x32 = "2", 0x40 = "@"
{
setDAC = vset2;
}
if ((incomingByte == 0x33) | (incomingByte == 0x23)) // 0x33 = "3", 0x23 = "#"
{
setDAC = vset3;
}
if ((incomingByte == 0x34) | (incomingByte == 0x24)) // 0x34 = "4", 0x24 = "$"
{
setDAC = vset4;
}
if ((incomingByte == 0x35) | (incomingByte == 0x25)) // 0x35 = "5", 0x25 = "%"
{
setDAC = vset5;
}
// update DAC value
DAC_Output(setDAC);
// output ON/OFF
if (incomingByte == 0x20) // 0x20 = " "
{
// toggle output
output_status = !output_status;
if (output_status == 0){
outputOFF();
}
else{
outputON();
}
}
// all OK, we finished parsing the serial data
}
}
UpdateSerial();
}
void UpdateSerial(void)
{
// read ADC values and update serial terminal every 500ms
// I used millis() to implement the delay as it does not
// interfere with Serial.read();
// Update the serial terminal
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// send update to serial monitor
Vtmp = getADC(2);
Vin = Vtmp * 0.0055;
Serial.print ("Vin = ");
Serial.print (Vin);
Vtmp = getADC(0);
Vsense = Vtmp * 0.0055;
Serial.print ("; Vsense = ");
Serial.print (Vsense);
if (output_status == 0){
Serial.println ("; Output Off");
}
else{
Vtmp = getADC(1);
Vout = Vtmp * 0.0055;
Serial.print ("; Vout = ");
Serial.println (Vout);
}
}
}
// DAC increments (0..4095) --> output voltage (0..Vref)
// 16 bit writes, first four bits are config bits:
// bit 15 A/B: DACA or DACB Select bit (1 = Write to DACB, 0 = Write to DACA)
// bit 14 BUF: VREF Input Buffer Control bit (1 = Buffered, 0 = Unbuffered)
// bit 13 GA: Output Gain Select bit
// 1 = 1x (VOUT = VREF * D/4096), 0 = 2x (VOUT = 2 * VREF * D/4096)
// bit 12 SHDN: Output Power Down Control bit
// 1 = Output Power Down Control bit
// 0 = Output buffer disabled, Output is high impedance
// bits 11:0 DATA BITS
void DAC_Output(unsigned int valueDAC)
{
char tmp;
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
// Select DAC chip
digitalWrite(DAC_CS, LOW);
// Send High Byte
tmp = (valueDAC >> 8) & 0x0F; // Store valueDAC[11..8] to tmp[3..0]
tmp |= 0x30; // GAIN = X1, SHDN = 1
SPI.transfer(tmp);
// Send Low Byte
tmp = valueDAC; // Store valueDAC[7..0] to tmp[7..0]
SPI.transfer(tmp);
// Deselect DAC chip
digitalWrite(DAC_CS, HIGH);
SPI.endTransaction();
}
// Get ADC values, returns 0..4095
unsigned int getADC(unsigned short channel)
{
unsigned int tmp;
SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE0));
// Select ACC chip
digitalWrite(ADC_CS, LOW);
SPI.transfer(0x06); // SPI communication using 8-bit segments
channel = channel << 6; // Bits 7 & 6 define ADC input
tmp = SPI.transfer(channel) & 0x0F; // Get first 8 bits of ADC value
tmp = tmp << 8; // Shift ADC value by 8
tmp = tmp | SPI.transfer(0); // Get remaining 4 bits of ADC value
digitalWrite(ADC_CS, HIGH); // Deselect MCP3204
return tmp; // Returns 12-bit ADC value
}
void outputON(void)
{
digitalWrite(OUT_PIN, HIGH);
}
void outputOFF(void)
{
digitalWrite(OUT_PIN, LOW);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment