I don’t really understand what you did. I’m assuming it makes more sense read as: // 4 as 2, l_cnt only goes 0 to 1 now.
But i don’t understand how its assigning it as A2+. How do I get it to be pins A0 and A1? Or A0 and A8? I don’t see where they assigned the pins.
I used a dmm and found v_ref is 4.93 (it was like 5.12 when lcd not hooked up). I’m sure it’ll change with servo added, I can test it later.
There’s no timing restriction/delay in that code, that I could see. I would say that it takes long enough to run, that for this controller, it’s a non-concern. Note each channel was sampled 10x and averaged, with 10 msec btw each sample. So it takes almost 400 msec to complete just the code above. In your case I’d take a sample of the voltage once per loop of the servo/switch/door code. Take some number (your choice) of samples and when done, compute the average and update the display.
Ohhh, so Num_samples = number of times voltage is checked for an average. I don’t want an average, I’d prefer a max voltage, averages are specifically why I am doing this isntead of pulling a software value easily from an lcd smartie plugin (the motherboard averages the value, and motherboard companies often will use firmware that averages in a way that makes it seem like the board is using less voltage than it really is, so reviewers will say things like ‘omg the asrock extreme is an awesome motherboard, it can do the same 5ghz overclock at only 1.4v, while the other boards needed 1.6v!’ when in reality it’s just giving a false voltage read.
Here’s an example of what I’m talking about, and a large part of why this needs to be hardwired rather than software:
http://www.youtube.com/watch?v=oB0dm2-nfpc
Also, averaging causes very important information in regards to voltage peaks and offsets to be lost, information that hardwiring gives. I know DMMs and voltmeters also read averages on some level, but they are more accurate and not as biased as motherboard firmware. I dont just want more accurate voltage reads here, I also want to know when and what causes vdroop and vpeak on my chip.
How did you come up with it taking 400msec to do the voltage reading? So I say, a sample of 1. I’m not sure I really follow what you mean.
So have you got the contrast and backlighting working ? According to the docs, apply 5v to pin 15 of the display. Ground pin 18 to turn on (100%) the blue LED. You also use a IO pin from the Arduino to pin 18 and put the brightness under software control via PWM. Same goes for the R and G LEDs.
http://arduino.cc/en/Reference/AnalogWrite
http://arduino.cc/en/Tutorial/PWM
The difference in your case (from the tutorial) is that a analogWrite(pin, 0) (= logic 0 = ground) is full on and a 255 is off.
Yea contrast is straightforward, with a pot on lcdpin3. I think I will put a pot on my computer case to make the contrast easily adjustable coolpoints!!!. It’s the backlighting brightness I’ve never been able to adjust, or to change the color of the LCD via coding. But now thanks to your help, I can!
I deleted the int brightness and brightness lines, and added analogWrite(XXXXLITE,0-255) and got it working! Super cool!
It seems if i ever shake the pins a bit, the lcd wigs out a bit and starts displaying crazy chars and stuff, that’s what was going on.
Anyways, is it possible for me to make the voltmetering more accurate, which I assume I have to do by reducing max voltage read? Like 0-3v? Couldn’t I make the DIVs like .5? So instead of scaling up voltage range to ~11v with div=11, make it .5 to make it to 2.5v? Or 1.78571429 for 2.8v max?
I’m hoping I can easily figure it out to have it where LCD smartie rules the top 2 lines, and 2x voltmeters for bottom 2 lines. I’m not sure if that means make it so each part of code thinks its a 2x20 display or just say its a 4x20, but i can play with that and figure it out.
This is my code:
/*--------------------------------------------------------------
Program: Voltmeter LCD
Description: 2 channel DC voltmeter with voltages displayed
on LCD to 1 decimal place
Hardware: Arduino Uno with voltage dividers on A2 to A5.
2 x 16 LCD connected to standard pins used in
Arduino example sketches from IDE.
Software: Developed using Arduino 1.0.5 software
Should be compatible with Arduino 1.0 +
Date: 27 May 2013
Author: W.A. Smith, http://startingelectronics.com
--------------------------------------------------------------*/
#include <LiquidCrystal.h>
// number of analog samples to take per reading, per channel
#define NUM_SAMPLES 1
// Samples of Voltage to be averaged for each read
#define DIV_1 1
#define DIV_2 1
// ADC reference voltage / calibration value
#define V_REF 4.93
#define REDLITE 6
#define GREENLITE 9
#define BLUELITE 10
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int sum[4] = {0}; // sums of samples taken
unsigned char sample_count = 0; // current sample number
float voltage[4] = {0.000}; // calculated voltages
char l_cnt = 0; // used in 'for' loops
void setup()
{
Serial.begin(9600);
lcd.begin(20, 4);
pinMode(REDLITE, OUTPUT);
pinMode(GREENLITE, OUTPUT);
pinMode(BLUELITE, OUTPUT);
}
void loop()
{
analogWrite(BLUELITE,0); //Blue brightness 255-0
analogWrite(REDLITE,255); //Red brightness 255-0
analogWrite(GREENLITE,255); //Green brightness 255-0
// take a number of analog samples and add them up
while (sample_count < NUM_SAMPLES) {
// sample each channel A2 to A5
for (l_cnt = 0; l_cnt < 2; l_cnt++) {
sum[l_cnt] += analogRead(A2 + l_cnt);
}
sample_count++;
delay(10);
}
// calculate the voltage for each channel
for (l_cnt = 0; l_cnt < 2; l_cnt++) {
voltage[l_cnt] = ((float)sum[l_cnt] / (float)NUM_SAMPLES * V_REF) / 1024.0;
}
// display voltages on LCD
// each voltage is multiplied by the resistor network
// division factor to calculate the actual voltage
// voltage 1 - A (pin A2)
lcd.setCursor(0, 2);
lcd.print("CPU VCORE ");
lcd.print(voltage[0] * DIV_1, 1);
lcd.print("v");
// voltage 2 - B (pin A3)
lcd.setCursor(0, 3);
lcd.print("CPU VRIN ");
lcd.print(voltage[1] * DIV_2, 1);
lcd.print("v");
// reset count and sums
sample_count = 0;
for (l_cnt = 0; l_cnt < 4; l_cnt++) {
sum[l_cnt] = 0;
}
}
It displays the voltages on the bottom 2 lines of my display, as CPU VCORE X.Xv and CPU VRIN X.Xv. When I measure one voltage, both change (and the 2nd usually off by a points or two), but when I short the other one for 0v it’s straight.
-
I don’t know how to get more decimal places. In definitions I changed to float voltage[4] = {0.000}; but it didn’t do it.
-
dont know how to change pin assignment
-
wondering if i can make it so its more accurate by like doing 0-3v instead.
This is both codes together:
/*--------------------------------------------------------------
Program: Voltmeter LCD
Description: 2 channel DC voltmeter with voltages displayed
on LCD to 1 decimal place
Hardware: Arduino Uno with voltage dividers on A2 to A5.
2 x 16 LCD connected to standard pins used in
Arduino example sketches from IDE.
Software: Developed using Arduino 1.0.5 software
Should be compatible with Arduino 1.0 +
Date: 27 May 2013
Author: W.A. Smith, http://startingelectronics.com
--------------------------------------------------------------*/
#include <LiquidCrystal.h>
// number of analog samples to take per reading, per channel
#define NUM_SAMPLES 1
// Samples of Voltage to be averaged for each read
#define DIV_1 1
#define DIV_2 1
// ADC reference voltage / calibration value
#define V_REF 4.93
#define REDLITE 6
#define GREENLITE 9
#define BLUELITE 10
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int sum[4] = {0}; // sums of samples taken
unsigned char sample_count = 0; // current sample number
float voltage[4] = {0.000}; // calculated voltages
char l_cnt = 0; // used in 'for' loops
void setup()
{
Serial.begin(9600);
lcd.begin(20, 4);
pinMode(REDLITE, OUTPUT);
pinMode(GREENLITE, OUTPUT);
pinMode(BLUELITE, OUTPUT);
lcd.setCursor(0,0);
lcd.print("Belial's Perfect Z87");//First line of text
lcd.setCursor(0,1);
lcd.print(" Intel i7-4770K"); //Second line of text
}
byte serial_getch(){
int incoming;
while (Serial.available()==0){}
// read the incoming byte:
incoming = Serial.read();
return (byte) (incoming &0xff);
}
void loop()
{
analogWrite(BLUELITE,0); //Blue brightness 255-0
analogWrite(REDLITE,255); //Red brightness 255-0
analogWrite(GREENLITE,255); //Green brightness 255-0
// take a number of analog samples and add them up
while (sample_count < NUM_SAMPLES) {
// sample each channel A2 to A5
for (l_cnt = 0; l_cnt < 2; l_cnt++) {
sum[l_cnt] += analogRead(A2 + l_cnt);
}
sample_count++;
delay(10);
}
// calculate the voltage for each channel
for (l_cnt = 0; l_cnt < 2; l_cnt++) {
voltage[l_cnt] = ((float)sum[l_cnt] / (float)NUM_SAMPLES * V_REF) / 1024.0;
}
// display voltages on LCD
// each voltage is multiplied by the resistor network
// division factor to calculate the actual voltage
// voltage 1 - A (pin A2)
lcd.setCursor(0, 2);
lcd.print("CPU VCORE ");
lcd.print(voltage[0] * DIV_1, 1);
lcd.print("v");
// voltage 2 - B (pin A3)
lcd.setCursor(0, 3);
lcd.print("CPU VRIN ");
lcd.print(voltage[1] * DIV_2, 1);
lcd.print("v");
// reset count and sums
sample_count = 0;
for (l_cnt = 0; l_cnt < 4; l_cnt++) {
sum[l_cnt] = 0;
byte rxbyte;
byte temp;
rxbyte = serial_getch();
if (rxbyte == 254) //Matrix Orbital uses 254 prefix for commands
{
switch (serial_getch())
{
case 66: //backlight on (at previously set brightness)
// not implemented
break;
case 70: //backlight off
// not implemented
break;
case 71: //set cursor position
temp = (serial_getch() - 1); //get column byte
switch (serial_getch()) //get row byte
{
//line 1 is already set up
case 2:
temp += 0x40;
break;
case 3:
temp += 0x14;
break;
case 4:
temp += 0x54;
break;
default:
break;
}
lcd.command(0b10000000 + temp);
break;
case 72: //cursor home (reset display position)
lcd.command(2);
break;
case 74: //show underline cursor
lcd.command(0b00001110);
break;
case 75: //underline cursor off
case 84: //block cursor off
lcd.command(0b00001100);
break;
case 76: //move cursor left
lcd.command(16);
break;
case 77: //move cursor right
lcd.command(20);
break;
case 78: //define custom char
lcd.command(64 + (serial_getch() * 8)); //get+set char address
for (temp = 7; temp != 0; temp--)
{
lcd.print(serial_getch()); //get each pattern byte
}
break;
case 83: //show blinking block cursor
lcd.command(0b00001111);
break;
case 86: //GPO OFF
//implement later
break;
case 87: //GPO ON
/*temp = serial_getch();
if (temp == 1)
{
GPO1 = GPO_ON;
}*/
break;
case 88: //clear display, cursor home
lcd.command(1);
break;
case 152: //set and remember (doesn't save value, though)
case 153: //set backlight brightness
//not implemented
break;
//these commands ignored (no parameters)
case 35: //read serial number
case 36: //read version number
case 55: //read module type
case 59: //exit flow-control mode
case 65: //auto transmit keypresses
case 96: //auto-repeat mode off (keypad)
case 67: //auto line-wrap on
case 68: //auto line-wrap off
case 81: //auto scroll on
case 82: //auto scroll off
case 104: //init horiz bar graph
case 109: //init med size digits
case 115: //init narrow vert bar graph
case 118: //init wide vert bar graph
break;
default:
//all other commands ignored and parameter byte discarded
temp = serial_getch(); //dump the command code
break;
}
return;
} //END OF COMMAND HANDLER
//change accented char to plain, detect and change descenders
//NB descenders only work on 5x10 displays. This lookup table works
// with my DEM-20845 (Display Elektronik GmbH) LCD using KS0066 chip.
switch (rxbyte)
{
//chars that have direct equivalent in LCD charmap
/* case 0x67: //g
rxbyte = 0xE7;
break;
case 0x6A: //j
rxbyte = 0xEA;
break;
case 0x70: //p
rxbyte = 0xF0;
break;
case 0x71: //q
rxbyte = 0xF1;
break;
case 0x79: //y
rxbyte = 0xF9;
break;
*/ case 0xE4: //ASCII "a" umlaut
rxbyte = 0xE1;
break;
case 0xF1: //ASCII "n" tilde
rxbyte = 0xEE;
break;
case 0xF6: //ASCII "o" umlaut
rxbyte = 0xEF; //was wrong in v0.86
break;
case 0xFC: //ASCII "u" umlaut
rxbyte = 0xF5;
break;
//accented -> plain equivalent
//and misc symbol translation
case 0xA3: //sterling (pounds)
rxbyte = 0xED;
break;
/* case 0xB0: //degrees symbol
rxbyte = 0xDF;
break;
*/ case 0xB5: //mu
rxbyte = 0xE4;
break;
case 0xC0: //"A" variants
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
rxbyte = 0x41;
break;
case 0xC8: //"E" variants
case 0xC9:
case 0xCA:
case 0xCB:
rxbyte = 0x45;
break;
case 0xCC: //"I" variants
case 0xCD:
case 0xCE:
case 0xCF:
rxbyte = 0x49;
break;
case 0xD1: //"N" tilde -> plain "N"
rxbyte = 0x43;
break;
case 0xD2: //"O" variants
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD8:
rxbyte = 0x4F;
break;
case 0xD9: //"U" variants
case 0xDA:
case 0xDB:
case 0xDC:
rxbyte = 0x55;
break;
case 0xDD: //"Y" acute -> "Y"
rxbyte = 0x59;
break;
/* case 0xDF: //beta //mucks up LCDSmartie's degree symbol??
rxbyte = 0xE2;
break;
*/ case 0xE0: //"a" variants except umlaut
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE5:
rxbyte = 0x61;
break;
case 0xE7: //"c" cedilla -> "c"
rxbyte = 0x63;
break;
case 0xE8: //"e" variants
case 0xE9:
case 0xEA:
case 0xEB:
rxbyte = 0x65;
break;
case 0xEC: //"i" variants
case 0xED:
case 0xEE:
case 0xEF:
rxbyte = 0x69;
break;
case 0xF2: //"o" variants except umlaut
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF8:
rxbyte = 0x6F;
break;
case 0xF7: //division symbol
rxbyte = 0xFD;
break;
case 0xF9: //"u" variants except umlaut
case 0xFA:
case 0xFB:
rxbyte = 0x75;
break;
default:
break;
}
lcd.write(rxbyte); //otherwise a plain char so we print it to lcd
}
}
They dont play well. uploads, is just like voltmeter code alone (1st line belials perfect…, 2nd line intel…, 3 and 4th voltmeters). Then when I start lcd smartie, 3rd line is voltmeter, 1st line is /?_?-?<-? and nothing on 2nd and 4th line and i cant change it no matter what i do from there, even if i turn off lcdsmartie.
On a side note, I think I’d like to incorporate timekeeping to this code (it’s hooked up to pc anyways for lcd stuff). Like 1st line has cpu temps and date, 2nd linje has gpu temps and time, or something. I tried to find code on it, i thought it’d be super simple, but its not. Not sure how to copy the code, like I dont know how to make time= something, and then call ‘time’ for stuff like lcdprint. I dont know what library to use, all the stuff online has so many different libraries and udpates and outdated so i cant make sense at all of how to do it. Like I see a lot of example sketches, but they really confuse me - how do you know you did the example right if you dont have an lcd telling you the time results? How do you know what time it is if the arduino has no display on it? I dont see any lquidcrystal lcd(…) in the codes. Everything i google to try to steal code uses an rtc.
I did realize, that in order to ‘do’ all this, my arduino will have data+ and data- hooked up to the pc, and then +/- to the powergen battery, and then lcd to +/- of the motherboard. Kinda funny.