How to Use a Screen to Display CPU Temp (not thermistor)?

Mee_n_Mac:
I simplified your code since you’re not averaging. I’m a little unsure of how to lcd.print a floating point number. If the code below doesn’t work right, I have an idea. Do NOT input voltages >2.54v !!

#include <LiquidCrystal.h>

#define DIV_1 1.0 //note it’s 1.0, not 1, to get full floating point accuracy
#define DIV_2 1.0
// ADC reference voltage / calibration value
#define V_REF 2.54 //use the measured Aref voltage
#define LOOPdelay 200 //measure the voltages and update the LCD every xxx msec
#define REDLITE 6
#define GREENLITE 9
#define BLUELITE 10

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//declare the variables used
float voltage1 = 0.0; // calculated voltages
float voltage2 = 0.0; // calculated voltages

void setup()
{
Serial.begin(9600);
lcd.begin(20, 4);
lcd.clear();
delay(LOOPdelay);
pinMode(REDLITE, OUTPUT);
pinMode(GREENLITE, OUTPUT);
pinMode(BLUELITE, OUTPUT);

analogReference(INTERNAL);
}

void loop(){
analogWrite(BLUELITE,0); //Blue brightness 255-0
analogWrite(REDLITE,255); //Red brightness 255-0
analogWrite(GREENLITE,255); //Green brightness 255-0
// sample each channel A0 and A1
voltage1 = DIV_1 * float((analogRead(A0)) * V_REF/1024.0);
voltage2 = DIV_2 * float((analogRead(A1)) * 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 A0)
lcd.setCursor(0, 2);
lcd.print("CPU VCORE ");
lcd.print(voltage1, 3);
lcd.print(“v”);
// voltage 2 - B (pin A1)
lcd.setCursor(0, 3);
lcd.print("CPU VRIN ");
lcd.print(voltage2, 3);
lcd.print(“v”);
delay(LOOPdelay); //give LCD time to process data
}





<QUOTE author="Belial88">

> Belial88:
> The values wig out when not connected/shorted, but whatever, but when I put it to that same 1.7v AA battery it reads as 2.0v. So how do i get that accurate and how do I get it to read 1.743v.

</QUOTE>
You had mis-set a constant in the defines. I'm surprised it displayed anything close to reality. You may need to increase the value for LOOPdelay to make things readable. Indeed you can play with that value to see how low it can go before your LCD stops working.

Hmm so… V_REF is based off the 5v pin, unless you write in the loop “analogReference(INTERNAL);” in which case it’l turn to whatever the value is, INTERNAL referencing the AREF pin. So… like I could say “13” if digitalpin 13 lead to a completely stable 5v value.

So the problem was that I wrote “INTERNAL” instead of 2.54v. And the arduino expects vref to be 2.54v because we wrote analogreference(INTERNAL) and Internal = AREF, ie 2.54v in my case and 2.56 usually.

Anyways, the code you wrote seems pretty much like it’s done. I see where the pin assignment is, it displays and is accurate to x.xxx. How did you do that? I don’t see anything where it’s 3 decimal places instead of 1. If anything, i see it say only 1 decimal place in

//declare the variables used
float voltage1 = 0.0;        // calculated voltages
float voltage2 = 0.0;        // calculated voltages

The loop delay figure, or how often the arduino sends voltage to lcd… i’m not sure why it makes much difference what it’s set to? I mean the difference in microseconds isn’t too big. I guess I could possibly miss a peak of suddenly insane voltage that I’d need to know… but 200msec is pretty quick, i guess I want as quick as possible right… i dont even know what is considered fast or slow.

So now to put it all together. I read that case…switch. So the case1 would be nothing, case2 would be if the button is pressed, ie 2 pins are shorted, for the servo. So starting with just LCD Smartie + Voltage reading:

#include <LiquidCrystal.h>

#define DIV_1    1.0           //note it's 1.0, not 1, to get full floating point accuracy
#define DIV_2    1.0
// ADC reference voltage / calibration value
#define V_REF    2.54         //use the measured Aref voltage
#define LOOPdelay 200       //measure the voltages and update the LCD every xxx msec
#define REDLITE 6
#define GREENLITE 9
#define BLUELITE 10

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//declare the variables used
float voltage1 = 0.0;        // calculated voltages
float voltage2 = 0.0;        // calculated voltages

//LCD SMARTIE
byte serial_getch(){
  int incoming;  
  while (Serial.available()==0){}
   // read the incoming byte:
  incoming = Serial.read();

  return (byte) (incoming &0xff);
}

void setup()
{
  Serial.begin(9600);
  lcd.begin(20, 4);
  lcd.clear();
  delay(LOOPdelay);
  pinMode(REDLITE, OUTPUT);
  pinMode(GREENLITE, OUTPUT);
  pinMode(BLUELITE, OUTPUT);
  
 analogReference(INTERNAL);
}

void loop(){
  analogWrite(BLUELITE,0); //Blue brightness 255-0
  analogWrite(REDLITE,255); //Red brightness 255-0
  analogWrite(GREENLITE,255); //Green brightness 255-0
  // sample each channel A0 and A1
  voltage1 = DIV_1 * float((analogRead(A0)) * V_REF/1024.0);
  voltage2 = DIV_2 * float((analogRead(A1)) * V_REF/1024.0);
  
  //Display Before LCD SMARTIE starts
  lcd.setCursor(0,0);
  lcd.print("LCD SMARTIE");
  lcd.setCursor(0,1);
  lcd.print("LCD SMARTIE");
  // display voltages on LCD
  // each voltage is multiplied by the resistor network
  // division factor to calculate the actual voltage
  // voltage 1 - A (pin A0)
  lcd.setCursor(0, 2);
  lcd.print("CPU VCORE ");
  lcd.print(voltage1, 3);
  lcd.print("v");
  // voltage 2 - B (pin A1)
  lcd.setCursor(0, 3);
  lcd.print("CPU VRIN  ");
  lcd.print(voltage2, 3);
  lcd.print("v");
  delay(LOOPdelay);         //give LCD time to process data
  
  
  //LCD SMARTIE
  byte rxbyte;  //this tells the 'compiler' to allocate some memory for a variable called rxbyte
  byte temp;    //this tells the 'compiler' to allocate some memory for a variable called temp
  rxbyte = serial_getch();     //this calls the 'function' serial_getch(), stores result in rxbyte 

  if (rxbyte == 254) //Matrix uses 254 for commands, if rxbyte = 254 the the code below runs
  {
    switch (serial_getch()) //calls serial_getch() to get the next byte from the PC
                            // 'switches' based on that byte
    {
    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;

    }
  }
}

Before lcd smartie starts, voltage reads are just frozen at some value (one shorted @0, the other is sometmies the battery value, sometimes just 0.134, for reference i short one and the other i measure the battery, but it isnt hardwired to the battery i just check it). Once lcd smartie starst, the voltage reads seem to work, but lcd smartie isnt

Belial88:

Mee_n_Mac:
You can use a voltage divider (a 10k pot) to do the same type of thing. Then you also use the internal AREF voltage of 2.56v.

If your other mobo voltage is > 2.8v, you can use a different voltage divider.

http://en.wikipedia.org/wiki/Voltage_divider

I’m sorry, I’m a little confused what you mean, and I know I’ve been confusing too.

One of my voltage ranges needs to max out at around 2.8v, but I’d be totally okay with it being 2.5v, especially for increased accuracy. Even maybe 2.4v would be okay. I say 2.8v as a good max voltage that leaves a ton of headroom (note, I am at ~2vrin and that’s after an extreme overclock, so much more than ~2.3vrin is really not necessary, but haswell’s die at around 2.6v and sometimes things like vPeaks can hit that high on certain boards or certain situations, which is why I wanted a bit more headroom. So, a max of 3v is okay, to keep things simple, I’d be totally okay with a max of 3v.

I guess the perfect max value would be like… 2.6v, but I really don’t mind it being between 2.5-3v.

So the max voltage I’ll read, for me, will likely be about 2.06v, maybe it spikes to 2.1v sometimes, but I wanted to make sure it could read up to about 2.5-3v. So what do you mean exactly, I use both the 5v and the 2.56 (or 2.4 in my case)v AREF so the voltage is doubly-calibrated? I just include both in the code? I’m a little confused where the pot comes in. Don’t I just write in a divider of .5?

I've explained this 5 or 6 times since page2. Did you read the wiki above ? Do you understand the principle explained there ? If you don't really need to measure any mobo voltage > 2.5v, skip the pot and tell the ADC to use the internal 2.56v reference. Just know that any voltage > 2.56v will read the same as 2.56v.

Belial88:
Before lcd smartie starts, voltage reads are just frozen at some value (one shorted @0, the other is sometmies the battery value, sometimes just 0.134, for reference i short one and the other i measure the battery, but it isnt hardwired to the battery i just check it). Once lcd smartie starst, the voltage reads seem to work, but lcd smartie isnt

The way I’d fix the conflict is to do 2 things. First I’d incorporate the “DVM code” into a hacked version of the Smartie code that runs on the Arduino. If you look at the small portion I posted earlier you can see 2 Smartie commands (brightness on, brightness off) that aren’t implemented in that version of the Smartie code. You could setup the Smartie on the PC to send those commands but nothing would happen at the Arduino end. By hacking those 2 unused functions you could tell the Arduino to sample the analog pin and send the scaled voltage to the LCD. So at the PC end you’d setup Smartie to display on line 3, "Voltage at DIMM = " (or whatever wording you desire on line 3) then have it send the brightness on command. At the Arduino, the Smartie code would put the characters on line 3 (in the same way it does for lines 1 and 2). Then when it reads the brightness on command it’ll put the A0 voltage on the LCD. Line 4 will work the same way but use the brightness off command to put up the A1 voltage. Now the refresh rate of the LCD is controlled from the PC and is the same timing for all the lines.

The servo code will then go into an interrupt service routine that runs only for a few 10’s of usecs whenever the push button is pressed. This means the switch will have to be wired to either pin 2 or 3 (to keep coding simple) but since there are conflicts in pin usage btw the servo and DVM code, some wiring changes are needed anyway.

http://arduino.cc/en/Reference/AttachInterrupt

If you can post the unchanged Arduino Smartie code you’re using (or a link to it) I’ll find 15 mins to do all the above and then it’s all done (assuming no bugs in my code).

Renate:
There are lots of problems with this merge of voltage reading and Smartie display.

Yes, this stuff is a bit hairy and complicated.

That’s the way real life is especially when trying to do two unrelated things simultaneously.

It's not all that hard or hairy. Rolling the DVM code into the Smartie is simple. Smartie, like Arduino, has a lot of "base" behind it so there's a lot of time saving there for the newbie. Now if I had a 32U4 based board to test with I'd reverse my course above. I'd put the Smartie code in the ISR and have some other code running in the loop(). That other code could poll the switch and issue the servo commands but would also be sampling the 2 analog channels and doing some processing, like a 1 sec running average, 1 sec max and mins, etc. Various re-purposed Smartie commands would then display some of these processed, or raw, data items ... in whatever mix was desired, controlled from the PC.

But I don’t have that board (nor that much inclination) so I’m keeping it simple. :shifty:

You are free to code up the Arduino and PC ends as you outlined above and give that to the OP. :mrgreen:

Mee_n_Mac:

Belial88:

Mee_n_Mac:
You can use a voltage divider (a 10k pot) to do the same type of thing. Then you also use the internal AREF voltage of 2.56v.

If your other mobo voltage is > 2.8v, you can use a different voltage divider.

http://en.wikipedia.org/wiki/Voltage_divider

I’m sorry, I’m a little confused what you mean, and I know I’ve been confusing too.

One of my voltage ranges needs to max out at around 2.8v, but I’d be totally okay with it being 2.5v, especially for increased accuracy. Even maybe 2.4v would be okay. I say 2.8v as a good max voltage that leaves a ton of headroom (note, I am at ~2vrin and that’s after an extreme overclock, so much more than ~2.3vrin is really not necessary, but haswell’s die at around 2.6v and sometimes things like vPeaks can hit that high on certain boards or certain situations, which is why I wanted a bit more headroom. So, a max of 3v is okay, to keep things simple, I’d be totally okay with a max of 3v.

I guess the perfect max value would be like… 2.6v, but I really don’t mind it being between 2.5-3v.

So the max voltage I’ll read, for me, will likely be about 2.06v, maybe it spikes to 2.1v sometimes, but I wanted to make sure it could read up to about 2.5-3v. So what do you mean exactly, I use both the 5v and the 2.56 (or 2.4 in my case)v AREF so the voltage is doubly-calibrated? I just include both in the code? I’m a little confused where the pot comes in. Don’t I just write in a divider of .5?

I've explained this 5 or 6 times since page2. Did you read the wiki above ? Do you understand the principle explained there ? If you don't really need to measure any mobo voltage > 2.5v, skip the pot and tell the ADC to use the internal 2.56v reference. Just know that any voltage > 2.56v will read the same as 2.56v.

I understand that a pot is a variable resistor, but I’m not sure I get it. Like I don’t understand where a dial, basically, a pot, has any relevance to the voltage measuring.

You keep saying skip the pot, but there was never a pot to begin with? I mean would I need a pot for if, say, i wanted to measure up to 2.8v? I would just set the divider to ~.56@5v reference, or better yet, now I’ve learned that I can just use a divider of like 1.17@2.56 reference for the same thing but more accurately (due to how much 5v fluctuates, and how little aref fluctuates, i assume).

I do understand analogReference better now, and that by default, my micro uses 5v as analog unless I command otherwise (internal, external - which would be cool to use some sort of reference battery! but i guess none exists ideally and isn’t necessary anyways), and the syntax of using analog reference (define V_REF is to state the voltage of reference, which we determine what is the reference in loop).

That’s good to know any voltage above 2.56v will read as 2.56, for a while i thought it meant above that = blow something.

Mee_n_Mac:

Belial88:
Before lcd smartie starts, voltage reads are just frozen at some value (one shorted @0, the other is sometmies the battery value, sometimes just 0.134, for reference i short one and the other i measure the battery, but it isnt hardwired to the battery i just check it). Once lcd smartie starst, the voltage reads seem to work, but lcd smartie isnt

The way I’d fix the conflict is to do 2 things. First I’d incorporate the “DVM code” into a hacked version of the Smartie code that runs on the Arduino. If you look at the small portion I posted earlier you can see 2 Smartie commands (brightness on, brightness off) that aren’t implemented in that version of the Smartie code. You could setup the Smartie on the PC to send those commands but nothing would happen at the Arduino end. By hacking those 2 unused functions you could tell the Arduino to sample the analog pin and send the scaled voltage to the LCD. So at the PC end you’d setup Smartie to display on line 3, "Voltage at DIMM = " (or whatever wording you desire on line 3) then have it send the brightness on command. At the Arduino, the Smartie code would put the characters on line 3 (in the same way it does for lines 1 and 2). Then when it reads the brightness on command it’ll put the A0 voltage on the LCD. Line 4 will work the same way but use the brightness off command to put up the A1 voltage. Now the refresh rate of the LCD is controlled from the PC and is the same timing for all the lines.

The servo code will then go into an interrupt service routine that runs only for a few 10’s of usecs whenever the push button is pressed. This means the switch will have to be wired to either pin 2 or 3 (to keep coding simple) but since there are conflicts in pin usage btw the servo and DVM code, some wiring changes are needed anyway.

http://arduino.cc/en/Reference/AttachInterrupt

If you can post the unchanged Arduino Smartie code you’re using (or a link to it) I’ll find 15 mins to do all the above and then it’s all done (assuming no bugs in my code).

I did this:

// include the library code:
#include <LiquidCrystal.h>

#define DIV_1    1.0           //note it's 1.0, not 1, to get full floating point accuracy
#define DIV_2    1.0
// ADC reference voltage / calibration value
#define V_REF    2.54         //use the measured Aref voltage
#define LOOPdelay 200       //measure the voltages and update the LCD every xxx msec
#define REDLITE 6
#define GREENLITE 9
#define BLUELITE 10

// these constants won't change.  But you can change the size of
// your LCD using them:
const int numRows = 4;
const int numCols = 20;

//declare the variables used
float voltage1 = 0.0;        // calculated voltages
float voltage2 = 0.0;        // calculated voltages

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12,6,11,5,4,3,2);
// RS, RW, Enable, 4,5,6,7 (Refer to the back of your LCD for details)

void setup() { 
  Serial.begin(9600);
  // set up the LCD's number of rows and columns: 
  lcd.begin(numRows, numCols);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("**LCD  SMARTIE**");
  lcd.setCursor(0,1);
  lcd.print("on Arduino");
  
  pinMode(REDLITE, OUTPUT);
  pinMode(GREENLITE, OUTPUT);
  pinMode(BLUELITE, OUTPUT);

analogReference(INTERNAL);
}

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
  byte rxbyte;
  byte temp;

  rxbyte = serial_getch();

  if (rxbyte == 254) //Matrix Orbital uses 254 prefix for commands
  {
    switch (serial_getch())
    {
    case 66: // sample each channel A0 and A1
  voltage1 = DIV_1 * float((analogRead(A0)) * V_REF/1024.0);            
  // voltage 1 - A (pin A0)
  lcd.setCursor(0, 2);
  lcd.print("CPU VCORE ");
  lcd.print(voltage1, 3);
  lcd.print("v");
      break;
      
    case 70:  // display voltages on LCD
  // each voltage is multiplied by the resistor network
  // division factor to calculate the actual voltage
  // voltage 1 - A (pin A0)
    voltage2 = DIV_2 * float((analogRead(A1)) * V_REF/1024.0);
  lcd.setCursor(0, 2);
  lcd.print("CPU VCORE ");
  lcd.print(voltage1, 3);
  lcd.print("v");
  // voltage 2 - B (pin A1)
  lcd.setCursor(0, 3);
  lcd.print("CPU VRIN  ");
  lcd.print(voltage2, 3);
  lcd.print("v");
  delay(LOOPdelay);         //give LCD time to process data          
      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

  }

I thought I totally executed your idea but it just didn’t work. It launches like the plain lcd smartie code ('lcd smartie//on arduino"), then i launch smartie and the characters on the lcd ‘flash’ like a different color or something (too quick to really tell) about every second.

Anyways, this is the LCD Smartie code. I pulled it from a tutorial online, that i struggled with at first because the pin assignment was extremely confusing (i didn’t know you could just leave out the 2nd number, RW, just fine, or that arduino would know that 6 of 7 values means you took out the 2nd value, and the guy used 2 different pinouts in 2 different pin diagrams that used different pinouts to the code).

As you pointed out, it’s just that loop code and the serial getch that makes it up.

f// include the library code:
#include <LiquidCrystal.h>

#define REDLITE 6
#define GREENLITE 9
#define BLUELITE 10

// these constants won't change.  But you can change the size of
// your LCD using them:
const int numRows = 4;
const int numCols = 20;

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12,6,11,5,4,3,2);
// RS, RW, Enable, 4,5,6,7 (Refer to the back of your LCD for details)

void setup() { 
  Serial.begin(9600);
  // set up the LCD's number of rows and columns: 
  lcd.begin(numRows, numCols);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("**LCD  SMARTIE**");
  lcd.setCursor(0,1);
  lcd.print("on Arduino");
   lcd.setCursor(0,2);
  lcd.print("*<3*");
  lcd.setCursor(0,3);
  lcd.print("Jeri");
  
  pinMode(REDLITE, OUTPUT);
  pinMode(GREENLITE, OUTPUT);
  pinMode(BLUELITE, OUTPUT);
 
}

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
  
  
  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

  }

The servo code will then go into an interrupt service routine that runs only for a few 10’s of usecs whenever the push button is pressed. This means the switch will have to be wired to either pin 2 or 3 (to keep coding simple) but since there are conflicts in pin usage btw the servo and DVM code, some wiring changes are needed anyway.

I’ll look into it, and I’ll work on adding the servo code to the lcd smartie code. I don’t mind wiring as long as I reduce the number of ‘lone’ pins (5v will have to be lone, or maybe 1 space away from ground) to help with paracord sleeving dupont connected wires.I’m using heatshrinkless paracord sleeving with dupont connectors on the arduino, using glue to hold it on the cable.

It appears on the Leonardo/Micro, 0/1/2/3/7 are all interrupts (instead of just 2/3, as in that linked interrupt tutorial and looking at pinout diagram).

So I did this to combine the servo and lcd smartie:

// include the library code:
#include <LiquidCrystal.h>
#include <VarSpeedServo.h>  //variable speed servo library

//declare the constants to be used
#define LEDPIN 13            //pin attached to led
#define servoPIN 3        //Servo control line 
#define SWitchPIN 2         //input from N.O. momentary switch

#define posOpenCMD 1900     //Define Clockwise Servo Limit in usec
#define posCloseCMD 600     //Define CounterClockwise Servo Limit in usec
#define DBdelay 200          //Duration of each button press in ms
#define MAXcnt 3            //Count of Button Presses needed for action
#define fastSPD 100         //speed setting; 1 = slowest, 255 is fastest (???)
#define slowSPD 15          //Speed Servo/Door opens and closes (15 is good average)

#define REDLITE 6
#define GREENLITE 9
#define BLUELITE 10

// these constants won't change.  But you can change the size of
// your LCD using them:
const int numRows = 4;
const int numCols = 20;

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12,11,5,4,7,2);
// RS, RW, Enable, 4,5,6,7 (Refer to the back of your LCD for details)

//declare the variables used
boolean wait = true;        //wait for motion to complete, or don't
boolean doorOPEN = false;   //desired door state set to closed
boolean SWstate = true;     //state of switch, open = TRUE = not pushed
byte SWcnt = 0;             //counter of same consecutive switch readings w/button = pressed

VarSpeedServo myServo; //create a servo object

volatile int state = LOW;

void setup() { 
  attachInterrupt(1, DoorMod, LOW);

  Serial.begin(9600);
  // set up the LCD's number of rows and columns: 
  lcd.begin(numRows, numCols);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("**LCD  SMARTIE**");
  lcd.setCursor(0,1);
  lcd.print("on Arduino");
  lcd.setCursor(0,2);
  lcd.print("*<3*");
  lcd.setCursor(0,3);
  lcd.print("Jeri");

  pinMode(REDLITE, OUTPUT);
  pinMode(GREENLITE, OUTPUT);
  pinMode(BLUELITE, OUTPUT);
  
  //set the pins to be ins or outs
  pinMode(LEDPIN, OUTPUT);
  digitalWrite(LEDPIN, LOW);  //turn LED off
  pinMode(servoPIN, OUTPUT);
  pinMode(SWitchPIN, INPUT_PULLUP);

  //CMD the servo to close the door
  myServo.attach(servoPIN);   // Attach the servo
  myServo.slowmove(posCloseCMD, fastSPD); // Tell servo to go to closed position

}

byte serial_getch(){

  int incoming;  
  while (Serial.available()==0){
  }
  // read the incoming byte:
  incoming = Serial.read();

  return (byte) (incoming &0xff);
}

void loop(){
  
   digitalWrite(servoPIN, state);
   
 
  analogWrite(BLUELITE,0); //Blue brightness 255-0
  analogWrite(REDLITE,255); //Red brightness 255-0
  analogWrite(GREENLITE,255); //Green brightness 255-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

}

void DoorMod()
{ 
  state= !state;
}

It appeared that when I would push the switch, the servo would move a bit, a random small amount (led also wouldn’t light up). Not sure what was going on, I thought I got it for sure.

Anyways, now my micro isn’t being picked up in Tools-> Serial Port. When I plug in, it is (but, like usual, it’s the wrong serial port), but once the arduino is no longer reset/flashing, after taht 10 second window, there is nothing in the serial port section (it’s grayed out). I hope nothing broke, from what i’ve read on line…

Looking at Devices & printers (w7 x64), it shows up as arduino micro on COMX-1 like normal during the start (bootloading? resetting?), and then it turns into ‘Unknown Device’ afterwards. I mean this just happened all the sudden. It makes the normal plugged in sounds. edit: - nvm, fixed. apparently it has something to do with uploading code as another device and so it doesnt have the proper usb driver (thus is shows up before bootloader is done, but doesnt once the code in it is implemented back on. answer was try to upload something basic like blink during bootloading process).

edit:2 okay every time i upload that code, this happens. Device dissapears from USB and I have to redo this trick to get it back on. I can’t verify lcd smartie works because it isn’t connected, but it does print the characters as stated in the code on the LCD. The servo doesn’t work, as I said, it just sort of makes stupid small movements.

Belial88:
I understand that a pot is a variable resistor, but I’m not sure I get it. Like I don’t understand where a dial, basically, a pot, has any relevance to the voltage measuring.

You keep saying skip the pot, but there was never a pot to begin with? I mean would I need a pot for if, say, i wanted to measure up to 2.8v? I would just set the divider to ~.56@5v reference, or better yet, now I’ve learned that I can just use a divider of like 1.17@2.56 reference for the same thing but more accurately (due to how much 5v fluctuates, and how little aref fluctuates, i assume).

I do understand analogReference better now, and that by default, my micro uses 5v as analog unless I command otherwise (internal, external - which would be cool to use some sort of reference battery! but i guess none exists ideally and isn’t necessary anyways), and the syntax of using analog reference (define V_REF is to state the voltage of reference, which we determine what is the reference in loop).

That’s good to know any voltage above 2.56v will read as 2.56, for a while i thought it meant above that = blow something.

Let's start at the beginning. If you leave the ADC ref voltage selection to the micro's "5"v, the conversion accuracy will be affected by changes in that 5v. Also 1 count of the ADC will be ~0.005v. You wanted a finer resolution. So you change the ADC ref voltage selection to "internal", mean the more stable 2.56v reference. The resolution is now ~0.0025v. But now 2.6v, 2.7v, 2.8v, etc will read all the same as 2.56v. **[u]You can't adjust the internal reference, it's whatever voltage it is. It doesn't change.[/u]** But it may not be exactly 2.56v. To improve the accuracy of your ADC calculations you can measure the actual voltage of your particular micro by selecting the ADC ref voltage selection to "internal", and then measuring it w/an accurate DVM at the AREF pin. Then use that actual, measured value in the *calculation of voltage from ADC counts* by making V_REF = that measured voltage ;

voltage1 = DIV_1 * float((analogRead(A0)) * V_REF/1023.0);

So a way to keep the better resolution is to add a voltage divider between the voltage to be measured and the ADC input. A pot is just an easy to adjust voltage divider. So with 2.8v across the pot, you could adjust the wiper of the pot so only 2.5v goes into the ADC. Of course any mobo voltage less than 2.8v is less than 2.5v, exactly 2.5/2.8 = 0.89285714285714285714285714285714 less. You then set the DIV_1 (and _2) numbers to be 2.8/2.5 = 1.12. That way when the ADC reads 2.5v, you know the mobo voltage is really 2.5v x 1.12 = 2.8v.

If you wanted to measure mobo voltages > 2.8v, like 3.0 or 3.3v, then adjust the wiper to get more reduction and alter the DIV_1, DIV_2 numbers accordingly. In fact the A0 and A1 pots could be adjusted differently from each other and then DIV_1 would be different from DIV_2. If either or both of the mobo voltages will always be < 2.56v (or whatever the actual ref voltage is) then you can skip the pot/divider since it’s not needed.

Belial88:
I thought I totally executed your idea but it just didn’t work. It launches like the plain lcd smartie code ('lcd smartie//on arduino"), then i launch smartie and the characters on the lcd ‘flash’ like a different color or something (too quick to really tell) about every second.

Anyways, this is the LCD Smartie code. I pulled it from a tutorial online, that i struggled with at first because the pin assignment was extremely confusing (i didn’t know you could just leave out the 2nd number, RW, just fine, or that arduino would know that 6 of 7 values means you took out the 2nd value, and the guy used 2 different pinouts in 2 different pin diagrams that used different pinouts to the code).

It appears on the Leonardo/Micro, 0/1/2/3/7 are all interrupts (instead of just 2/3, as in that linked interrupt tutorial and looking at pinout diagram).

I had a quick look at your code. You were pretty close, just a couple of mistakes. I'll look some more and provide feedback tomorrow.

Meanwhile here’s my unchecked code. See if it compiles and runs properly. Check the defines for the new wiring. As you pointed out, the switch want’s to be one of a few pins. As do the backlight control pins, if you ever want the code to affect the brightness or color. Note that use of the VarSpeedServo disables a pin (D5) from doing PWM (aka analogWrite) duty. I reserved pins 0 & 1 (UART) for future use. Thus the new wiring.

#include <VarSpeedServo.h>  //variable speed servo library
#include <LiquidCrystal.h>

//declare the constants to be used
#define LEDPIN 13             //pin attached to LED
#define servoPIN 9            //Servo control line
#define SWitchPIN 2           //input from N.O. momentary switch
#define redPIN 11             //PWM pin for red LED backlight
#define greenPIN 10           //PWM pin for green LED backlight
#define bluePIN 12            //PWM pin for blue LED backlight
#define rsPIN 8               //reset pin for LCD
#define enablePIN 3           //enable pin for LCD
#define d4PIN 4               //data pin4 for LCD
#define d5PIN 5               //data pin5 for LCD
#define d6PIN 6               //data pin6 for LCD
#define d7PIN 7               //data pin7 for LCD
// these constants won't change.  But you can change the size of
// your LCD using them:
const int numRows = 4;
const int numCols = 20;

#define posOpenCMD 1900       //Define Clockwise Servo position in usec
#define posCloseCMD 600       //Define CounterClockwise Servo position in usec
#define DBdelay 2000          //Min time needed btw any 2 button presses, in msec
#define fastSPD 100           //speed setting; 1 = slowest, 255 is fastest (???)
#define slowSPD 15            //Speed Servo/Door opens and closes (15 is good average)
#define DIV_1    1.0          //gain correction for A0 channel
#define DIV_2    1.0          //note it's 1.0, not 1, to get full floating point accuracy

#define V_REF    2.54         //use the measured Aref voltage

//declare the variables used

volatile boolean doorOPEN = false;   //desired door state set to closed
byte rxbyte = 0;                     //rxbyte is the received byte from Smartie
byte temp = 0;
volatile unsigned long SWtime = 0;   //holds the time of the last valid switch push
float voltage1 = 0.0;                // calculated voltage for A0
float voltage2 = 0.0;                // calculated voltage for A1

LiquidCrystal lcd(rsPIN, enablePIN, d4PIN, d5PIN, d6PIN, d7PIN);
VarSpeedServo myServo; //create a servo object

void setup() {
  //set the pins to be ins or outs
  pinMode(LEDPIN, OUTPUT);
  digitalWrite(LEDPIN, LOW);            //turn LED off
  pinMode(servoPIN, OUTPUT);
  pinMode(SWitchPIN, INPUT_PULLUP);
  pinMode(redPIN, OUTPUT);
  pinMode(greenPIN, OUTPUT);
  pinMode(bluePIN, OUTPUT);

  attachInterrupt(1, SW_ISR, FALLING);

  Serial.begin(9600);

  lcd.begin(numCols, numRows);
  lcd.clear();

  analogWrite(bluePIN,0);                //Blue brightness 255-0
  analogWrite(redPIN,255);               //Red brightness 255-0
  analogWrite(greenPIN,255);             //Green brightness 255-0

  analogReference(INTERNAL);              //use the internal 2.56v ADC reference

  //CMD the servo to close the door
  myServo.attach(servoPIN);               // Attach the servo
  myServo.slowmove(posCloseCMD, fastSPD); // Tell servo to go to closed position
  
  //put a hello world on the LCD
  lcd.home();
  lcd.print("Line 1");
  lcd.setCursor(10, 1);
  lcd.print("Line 2");
  lcd.setCursor(20, 2);
  lcd.print("Line 3");
  lcd.setCursor(30, 3);
  lcd.print("Line 4");
}


//the following function is the ISR that responds to the push button switch
//it commands the door to open or close at slow speed
void SW_ISR(){
  //debounce the switch by ignoring any interrupt that occurs too soon after the prior one
  unsigned long Time = millis();
  if(Time - SWtime > DBdelay){            //enough time has elapsed, not a switch bounce
    SWtime = Time;                        //save new time of switch push
    doorOPEN = !doorOPEN;                 //reverse desired door state
    if(doorOPEN == true){
      digitalWrite(LEDPIN, HIGH);         //turn LED on
      myServo.slowmove(posOpenCMD, slowSPD);    //tell servo to go to open position
    }
    else {
      digitalWrite(LEDPIN, LOW);          //turn LED off
      myServo.slowmove(posCloseCMD, slowSPD);   //tell servo to go to closed position
    }
  }
}


//this function is used by the smartie code to get data from the PC
byte serial_getch(){
  int incoming; 
  while (Serial.available()==0){
  }
  // read the incoming byte:
  incoming = Serial.read();
  return (byte) (incoming &0xff);
}


//the main loop is now just the hacked version of the Arduino Smartie code
void loop(){
  rxbyte = serial_getch();   //this calls the 'function' serial_getch(), stores result in rxbyte
  if (rxbyte == 254)     //Matrix uses 254 for commands, if rxbyte = 254 the the code below runs
  {
    switch (serial_getch())  //calls serial_getch() to get the next byte from the PC
    {
    case 66: //former backlight on command, now hacked to sample A0 and send voltage to LCD
      voltage1 = DIV_1 * float((analogRead(A0)) * V_REF/1023.0);            
      lcd.print(voltage1, 3);
      lcd.print("v");
      break;
    case 70: //former backlight off command, now hacked to sample A1 and send voltage to LCD
      voltage2 = DIV_2 * float((analogRead(A1)) * V_REF/1023.0);
      lcd.print(voltage2, 3);
      lcd.print("v");
      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
}

I’m hoping the code above also solves your disappearing Micro problem. :?

Let’s start at the beginning. If you leave the ADC ref voltage selection to the micro’s "5"v, the conversion accuracy will be affected by changes in that 5v. Also 1 count of the ADC will be ~0.005v. You wanted a finer resolution. So you change the ADC ref voltage selection to “internal”, mean the more stable 2.56v reference. The resolution is now ~0.0025v. But now 2.6v, 2.7v, 2.8v, etc will read all the same as 2.56v. You can’t adjust the internal reference, it’s whatever voltage it is. It doesn’t change. But it may not be exactly 2.56v. To improve the accuracy of your ADC calculations you can measure the actual voltage of your particular micro by selecting the ADC ref voltage selection to “internal”, and then measuring it w/an accurate DVM at the AREF pin. Then use that actual, measured value in the calculation of voltage from ADC counts by making V_REF = that measured voltage

Hm, I think I said I wanted at least .01 accuracy, and being okay with maybe .03v tops. I might’ve said that like .001 accuracy would be awesome, or x.xxx. .005v is great! I think just that I’d prefer higher accuracy, rather than higher max voltage, as that what seemed to be the trade-off. I did find that my AREF pin = 2.54v (my DMM reads like .01/.02 on the 200ohm setting, so it’s accurate).

So a way to keep the better resolution is to add a voltage divider between the voltage to be measured and the ADC input. A pot is just an easy to adjust voltage divider. So with 2.8v across the pot, you could adjust the wiper of the pot so only 2.5v goes into the ADC. Of course any mobo voltage less than 2.8v is less than 2.5v, exactly 2.5/2.8 = 0.89285714285714285714285714285714 less. You then set the DIV_1 (and _2) numbers to be 2.8/2.5 = 1.12. That way when the ADC reads 2.5v, you know the mobo voltage is really 2.5v x 1.12 = 2.8v.

If you wanted to measure mobo voltages > 2.8v, like 3.0 or 3.3v, then adjust the wiper to get more reduction and alter the DIV_1, DIV_2 numbers accordingly. In fact the A0 and A1 pots could be adjusted differently from each other and then DIV_1 would be different from DIV_2. If either or both of the mobo voltages will always be < 2.56v (or whatever the actual ref voltage is) then you can skip the pot/divider since it’s not needed.

Well CPU Vcore will never, ever go up past ~1.6v, much less 2+. CPU VRIN wont really ever go past 2.5… but it’s possible in very extreme cases. I think I understand, so I put a pot on the line between measured device and arduino, but how would I adjust it exactly? How would I know what exact divider it’s on?

Belial88:
Well CPU Vcore will never, ever go up past ~1.6v, much less 2+. CPU VRIN wont really ever go past 2.5… but it’s possible in very extreme cases. I think I understand, so I put a pot on the line between measured device and arduino, but how would I adjust it exactly? How would I know what exact divider it’s on?

You could decide on a max voltage for the VRIN that would be measured and derive the divider ratio from that, just like 2.8v got me 0.89285714285714285714285714285714 above. Then take your battery as a source, measure it's full voltage and the compute the divided voltage that would indicate that it's adjusted to get the desired ratio. Then measure the wiper voltage and adjust the pot until you get that voltage.

ie - if the battery measures 1.8v and you want a 0.89285714285714285714285714285714 ratio, then measure the pot output and adjust it until you read 1.8v x 0.89285714285714285714285714285714 = 1.6071v. Then you’ll know 2.8v VRIN will be 2.5v at the ADC and, for a perfect ADC, multiply it’s counts by 1.12 will get you a 2.8v reading.

A real ADC might have 2 counts of error and if you really wanted to you could try to calibrate the ADC as well. But then the question would be, which has more error, the Arduino ADC or the DVM’s ADC ?

hmm let me understand this. so… I would wire the analog/ground as i’ve been doing for voltage reading. But I’d install a pot on the line… so middle pin to arduino, and one end would be to… not 5v but aref? I’d really be using a rheostat right (variable resistor…?)

So i use this pot lined voltage reader… on the battery. I’m confused, why dont I just use 1.12 as my divider (2.8/2.5, or I want it to read up to 2.8 from 2.5v reference, or make the max 2.8 instead of 2.5) and I’m good to go? So the point of the pot is for calibration, but why do I need to do that?

But yea, I’m more open to using different voltages on each, because CPU VRIN really doesn’t need to be as accurate as VCORE. So 2.56v for vcore read, and then for vrin, i mean i could still probably use 2.56v but i’m still confused and interested in this idea. I’m trying to google this stuff but not having much success.

I had a quick look at your code. You were pretty close, just a couple of mistakes. I’ll look some more and provide feedback tomorrow.

Hm, 1023 not 1024. I also copied a part a second time but that setcursor somewhere else so i dont know if that wouldve stopped it all from working. you also remove byte rxbytw and byte temp (dont know those). you put the lcd brightness settings of 0-255 in setup instead of loop, that’s weird.

Note that use of the VarSpeedServo disables a pin (D5) from doing PWM (aka analogWrite) duty. I reserved pins 0 & 1 (UART) for future use. Thus the new wiring.

UART… could I use UART to communicate to the pc, instead of the usb? Because as it is, I will have to hack up the usb line, where d+/d- will go to my pc, and then red/black will go to the powergen usb battery charger pack. not a big deal, just curious. or do i need usb here?

anyways, im not sure i follow what you mean about varspeedservo disabling a pin from pwm. it disables the lcd from doing pwm? do you mean pin 5, not d5 from lcd? Why does it do this? The lcd data pins dont have to be pwm though right, so doesnt matter if its d5 or 5 that cant do pwm…but pin5 on the arduino is pwm.

#include <VarSpeedServo.h>  //variable speed servo library
#include <LiquidCrystal.h>

//declare the constants to be used
#define LEDPIN 13             //pin attached to LED
#define servoPIN 9            //Servo control line
#define SWitchPIN 2           //input from N.O. momentary switch
#define redPIN 12             //PWM pin for red LED backlight
#define greenPIN 11           //PWM pin for green LED backlight
#define bluePIN 10            //PWM pin for blue LED backlight
#define rsPIN 8               //reset pin for LCD
#define enablePIN 3           //enable pin for LCD
#define d4PIN 4               //data pin4 for LCD
#define d5PIN 5               //data pin5 for LCD
#define d6PIN 6               //data pin6 for LCD
#define d7PIN 7               //data pin7 for LCD
// these constants won't change.  But you can change the size of
// your LCD using them:
const int numRows = 4;
const int numCols = 20;

#define posOpenCMD 1900       //Define Clockwise Servo position in usec
#define posCloseCMD 600       //Define CounterClockwise Servo position in usec
#define DBdelay 2000          //Min time needed btw any 2 button presses, in msec
#define fastSPD 100           //speed setting; 1 = slowest, 255 is fastest (???)
#define slowSPD 15            //Speed Servo/Door opens and closes (15 is good average)
#define DIV_1    1.0          //gain correction for A0 channel
#define DIV_2    1.0          //note it's 1.0, not 1, to get full floating point accuracy

#define V_REF    2.54         //use the measured Aref voltage

//declare the variables used

volatile boolean doorOPEN = false;   //desired door state set to closed
byte rxbyte = 0;                     //rxbyte is the received byte from Smartie
byte temp = 0;
volatile unsigned long SWtime = 0;   //holds the time of the last valid switch push
float voltage1 = 0.0;                // calculated voltage for A0
float voltage2 = 0.0;                // calculated voltage for A1

LiquidCrystal lcd(rsPIN, enablePIN, d4PIN, d5PIN, d6PIN, d7PIN);
VarSpeedServo myServo; //create a servo object

void setup() {
  //set the pins to be ins or outs
  pinMode(LEDPIN, OUTPUT);
  digitalWrite(LEDPIN, LOW);            //turn LED off
  pinMode(servoPIN, OUTPUT);
  pinMode(SWitchPIN, INPUT_PULLUP);
  pinMode(redPIN, OUTPUT);
  pinMode(greenPIN, OUTPUT);
  pinMode(bluePIN, OUTPUT);

  attachInterrupt(1, SW_ISR, FALLING);

  Serial.begin(9600);

  lcd.begin(numCols, numRows);
  lcd.clear();

  analogWrite(bluePIN,0);                //Blue brightness 255-0
  analogWrite(redPIN,255);               //Red brightness 255-0
  analogWrite(greenPIN,255);             //Green brightness 255-0

  analogReference(INTERNAL);              //use the internal 2.56v ADC reference

  //CMD the servo to close the door
  myServo.attach(servoPIN);               // Attach the servo
  myServo.slowmove(posCloseCMD, fastSPD); // Tell servo to go to closed position
  
  //put a hello world on the LCD
  lcd.home();
  lcd.print("lcd smartie");
  lcd.setCursor(0, 1);
  lcd.print("arduino");
  lcd.setCursor(0, 2);
  lcd.print("Line 3");
  lcd.setCursor(0, 3);
  lcd.print("Line 4");
}


//the following function is the ISR that responds to the push button switch
//it commands the door to open or close at slow speed
void SW_ISR(){
  //debounce the switch by ignoring any interrupt that occurs too soon after the prior one
  unsigned long Time = millis();
  if(Time - SWtime > DBdelay){            //enough time has elapsed, not a switch bounce
    SWtime = Time;                        //save new time of switch push
    doorOPEN = !doorOPEN;                 //reverse desired door state
    if(doorOPEN == true){
      digitalWrite(LEDPIN, HIGH);         //turn LED on
      myServo.slowmove(posOpenCMD, slowSPD);    //tell servo to go to open position
    }
    else {
      digitalWrite(LEDPIN, LOW);          //turn LED off
      myServo.slowmove(posCloseCMD, slowSPD);   //tell servo to go to closed position
    }
  }
}


//this function is used by the smartie code to get data from the PC
byte serial_getch(){
  int incoming; 
  while (Serial.available()==0){
  }
  // read the incoming byte:
  incoming = Serial.read();
  return (byte) (incoming &0xff);
}


//the main loop is now just the hacked version of the Arduino Smartie code
void loop(){
  rxbyte = serial_getch();   //this calls the 'function' serial_getch(), stores result in rxbyte
  if (rxbyte == 254)     //Matrix uses 254 for commands, if rxbyte = 254 the the code below runs
  {
    switch (serial_getch())  //calls serial_getch() to get the next byte from the PC
    {
    case 66: //former backlight on command, now hacked to sample A0 and send voltage to LCD
      voltage1 = DIV_1 * float((analogRead(A0)) * V_REF/1023.0);   
      lcd.setCursor(0,2);
      lcd.print("CPU VCORE ");   
      lcd.print(voltage1, 3);
      lcd.print("v");
      break;
    case 70: //former backlight off command, now hacked to sample A1 and send voltage to LCD
      voltage2 = DIV_2 * float((analogRead(A1)) * V_REF/1023.0);
      lcd.setCursor(0,3);
      lcd.print("CPU VRIN ");
      lcd.print(voltage2, 3);
      lcd.print("v");
      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
}

I added a few lines by the LCD voltmetering in the loop by the cases, so itd read cpu vcore and cpu vrin. you also left out setcursor. Also in setup there’s line1/line2/line3/line4 but it is on (nothing, which seems to mean 0,0)/10,1/20,2/30,3 which i guess you just added that decimal where it shoudl just be zero, i changed that (so 0,0/0,1/0,2/0,3). And I switch around some backlight pins (still same 3 pins though). Above code reflects those changes

But i cant get the lcd voltmeter part to work. it just isn’t there, with lcd smartie on or off (and smartie can write on those lines too).

the servo works, part about button being falling instead of low is an awesome idea. No more weird usb lockout either.

volatile unsigned long SWtime = 0; //holds the time of the last valid switch push

dont understand this line (a few others idont get, like rxbyte and temp and stuff but this is the only adjustable one i dont get).

Finally, the servo sort of buzzes and bizzes when at idle (at both positions). Like just a couple random seconds go by, and then it’ll buzz a bit. It buzzes for random time (split second to a full 2 seconds) and random gaps (2 minutes before buzz, 10 seconds, etc). I think this has alwaeys been the case, but I just assumed ‘well im sure it’ll smooth out when i code the positions better or solder the connections’ but this is pretty good. I searched stuff like ‘buzz at idle arduino’ and they say dont use analog for servo control, digital is way better. But… i think we are using digital right (i mean its not on the analog pin). I mean i know my breadboard connections aren’t too solid but the lcd doesnt flicker at all or anything, the servo works smoothly in operation, I know it’s in proper wiring.

Belial88:
Hm, 1023 not 1024. I also copied a part a second time but that setcursor somewhere else so i dont know if that wouldve stopped it all from working. you also remove byte rxbytw and byte temp (dont know those). you put the lcd brightness settings of 0-255 in setup instead of loop, that’s weird.

The 1023 is the correct number, though I doubt the difference is in anyway significant. The declarations for rxbyte and temp were moved to where other such variables are declared. I put the brightness controls in setup() as the weren't changing and so only need to run once. Remember that any code in the loop() will only run when the Smartie code is done processing a command or sending a character to the LCD. That's perhaps 40 - 80 times (in a burst) every refresh cycle (as set by the Smartie control GUI on the PC. That's because the Smartie code sits there polling the USB until data comes in and only then does all the code in the loop() run.

Belial88:
UART… could I use UART to communicate to the pc, instead of the usb? Because as it is, I will have to hack up the usb line, where d+/d- will go to my pc, and then red/black will go to the powergen usb battery charger pack. not a big deal, just curious. or do i need usb here?

anyways, im not sure i follow what you mean about varspeedservo disabling a pin from pwm. it disables the lcd from doing pwm? do you mean pin 5, not d5 from lcd? Why does it do this? The lcd data pins dont have to be pwm though right, so doesnt matter if its d5 or 5 that cant do pwm…but pin5 on the arduino is pwm.

You could use the UART, it would be more coding and you'd need a USB-serial converter as well.

From the VarSpeedServo library VarSpeedServo.cpp file ;

https://github.com/netlabtoolkit/VarSpe … dServo.cpp

Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached. Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four.

For your Micro that’s timer3 that’s used and that seems to go only to the Arduino pin5 (labelled D5 on the schematic). So pin5 can’t do the analogWrite function.

Belial88:
But i cant get the lcd voltmeter part to work. it just isn’t there, with lcd smartie on or off (and smartie can write on those lines too).

How are you configuring Smartie to send the brightness on and off commands ?

Belial88:
dont understand this line

SWtime holds the time of the last valid switch push. Anytime the switch is pushed, **or bounces**, the ISR runs. If the time difference btw any 2 pushes is less that 2 secs, the later is considered a bounce, not a push and so the door command remains unchanged.

Belial88:
hmm let me understand this. so… I would wire the analog/ground as i’ve been doing for voltage reading. But I’d install a pot on the line… so middle pin to arduino, and one end would be to… not 5v but aref? I’d really be using a rheostat right (variable resistor…?)

So i use this pot lined voltage reader… on the battery. I’m confused, why dont I just use 1.12 as my divider (2.8/2.5, or I want it to read up to 2.8 from 2.5v reference, or make the max 2.8 instead of 2.5) and I’m good to go? So the point of the pot is for calibration, but why do I need to do that?

But yea, I’m more open to using different voltages on each, because CPU VRIN really doesn’t need to be as accurate as VCORE. So 2.56v for vcore read, and then for vrin, i mean i could still probably use 2.56v but i’m still confused and interested in this idea. I’m trying to google this stuff but not having much success.

myself:
So a way to keep the better resolution is to add a voltage divider between the voltage to be measured and the ADC input. A pot is just an easy to adjust voltage divider. So with 2.8v across the pot, you could adjust the wiper of the pot so only 2.5v goes into the ADC. Of course any mobo voltage less than 2.8v is less than 2.5v, exactly 2.5/2.8 = 0.89285714285714285714285714285714 less. You then set the DIV_1 (and _2) numbers to be 2.8/2.5 = 1.12. That way when the ADC reads 2.5v, you know the mobo voltage is really 2.5v x 1.12 = 2.8v.

So the “top” of the divider goes to the voltage to be divided, in this case the mobo voltage CPU VRIN, the one voltage that might ever be > than the ADC ref voltage, the one that might be 2.8v. That way if CPU VRIN is ever > 2.5v, the voltage at the wiper (input to the ADC) will be < 2.5v, therefore less than the ADC ref voltage and thus won’t be pegged at 1023 counts. Because any voltage input to the ADC that is > the ADC ref voltage will read 1023.

1/1.12 = 0.89285714285714285714285714285714

Okay I see, grnd to grnd, middle to analogpin, top to vrin. And the point of the pot is calibration, I calibrate and figure what i need and then remove it from the line.

But I still am confused. Why do I need the pot at all? I want to measure, say 2.8 as max. I just do the math, 2.5 / 2.8 = .89… . 1 / .089 = 1.12, there’s my divider. Why use the pot?

How are you configuring Smartie to send the brightness on and off commands ?

I’m not. I think there’s a way you can change brightness from lcd smartie but I haven’t messed with it at all. I meant like with lcd smartie program being on or off.

SWtime holds the time of the last valid switch push. Anytime the switch is pushed, or bounces, the ISR runs. If the time difference btw any 2 pushes is less that 2 secs, the later is considered a bounce, not a push and so the door command remains unchanged.

where are you getting 2 seconds from? Wouldn’t it be 0 seconds as it’s currently written (volatile unsigned long SWtime = 0; ). That’s really cool though.

Belial88:
Okay I see, grnd to grnd, middle to analogpin, top to vrin. And the point of the pot is calibration, I calibrate and figure what i need and then remove it from the line.

But I still am confused. Why do I need the pot at all? I want to measure, say 2.8 as max. I just do the math, 2.5 / 2.8 = .89… . 1 / .089 = 1.12, there’s my divider. Why use the pot?

myself:
Because any voltage input to the ADC that is > the ADC ref voltage will read 1023.

Stop and think, w/o the pot how would the ADC measure 2.6v ? Or 2.7v ? Or 2.8v ?

Belial88:

myself:
How are you configuring Smartie to send the brightness on and off commands ?

I'm not. I think there's a way you can change brightness from lcd smartie but I haven't messed with it at all. I meant like with lcd smartie program being on or off.
Perhaps you didn't get the post where I explained the concept of how this part was to work. When LCDSmartie on the PC sends a brightness on command, what will the code running on the Arduino do ? Same question, but for brightness off ? What needs to happen for those lines of code, that you modified (looked good), to ever run ?

Now if you can’t find the brightness commands, there were other unused (at the Arduino end) commands. See if you can find 2 you like.

Belial88:

myself:
SWtime holds the time of the last valid switch push. Anytime the switch is pushed, or bounces, the ISR runs. If the time difference btw any 2 pushes is less that 2 secs, the later is considered a bounce, not a push and so the door command remains unchanged.

where are you getting 2 seconds from? Wouldn't it be 0 seconds as it's currently written (volatile unsigned long SWtime = 0; ). That's really cool though.
Look at the code in the ISR. It also uses a constant that equals 2 sec. The line you looked just declares SWtime to be a variable (all variables and constants must be declared) and initializes it to = zero. SWtime is also set inside the ISR.

http://arduino.cc/en/Reference/Millis

Stop and think, w/o the pot how would the ADC measure 2.6v ? Or 2.7v ? Or 2.8v ?

ohh okay… so you really just need a resistor in the line… but a resistor might not always exist for what you want, so you just use a pot. And so you turn the max voltage you want into 2.56v (or 2.54 in my case if aref = 2.54). But since having a 2.8v thing isnt always on hand, you can just make, like, 1.8v x (AREF / Max Voltage Wanted, or .89 for 2.8v) = 1.602…

so really, for 2.8v, you just put a 89% Resistor on the line and then put the divider to whatever. I googled 89% resistors but couldnt find any. Maybe i could use like a 90% resistor or whatever is commonly sold and settle for like 2.81v… or just use a pot.

Perhaps you didn’t get the post where I explained the concept of how this part was to work. When LCDSmartie on the PC sends a brightness on command, what will the code running on the Arduino do ? Same question, but for brightness off ? What needs to happen for those lines of code, that you modified (looked good), to ever run ?

Now if you can’t find the brightness commands, there were other unused (at the Arduino end) commands. See if you can find 2 you like.

It doesnt ever send brightness commands because… we set the lcd to just be on in setup.

DBdelay is 2000! And then if(Time - SWtime > DBdleay) means if the time of button press - 2nd button press is great than DBdelay (set to 2s), it will activate.

okay so i see what you are getting at, if I go into lcd smartie and hit ‘backlight on’ one of the lines comes up, then backlight off and the other one comes up. But I dont see any commands in the arduino code that i understand dont do anything.

The trhing is that they dont update unless i hit backlight on/off/on/off, and the first one (cpu vcore in this code), always has a couple weird characters behind it because it displays right away when i start lcd smartie (i guess because lcd backlight on). so how to make it refresh more and how to avoid those weird chars…

#include <VarSpeedServo.h>  //variable speed servo library
#include <LiquidCrystal.h>

//declare the constants to be used
#define LEDPIN 13             //pin attached to LED
#define servoPIN 9            //Servo control line
#define SWitchPIN 2           //input from N.O. momentary switch
#define redPIN 12             //PWM pin for red LED backlight
#define greenPIN 11           //PWM pin for green LED backlight
#define bluePIN 10            //PWM pin for blue LED backlight
#define rsPIN 8               //reset pin for LCD
#define enablePIN 3           //enable pin for LCD
#define d4PIN 4               //data pin4 for LCD
#define d5PIN 5               //data pin5 for LCD
#define d6PIN 6               //data pin6 for LCD
#define d7PIN 7               //data pin7 for LCD
// these constants won't change.  But you can change the size of
// your LCD using them:
const int numRows = 4;
const int numCols = 20;

#define posOpenCMD 1900       //Define Clockwise Servo position in usec
#define posCloseCMD 600       //Define CounterClockwise Servo position in usec
#define DBdelay 2000          //Min time needed btw any 2 button presses, in msec
#define fastSPD 100           //speed setting; 1 = slowest, 255 is fastest (???)
#define slowSPD 15            //Speed Servo/Door opens and closes (15 is good average)
#define DIV_1    1.0          //gain correction for A0 channel
#define DIV_2    1.0          //note it's 1.0, not 1, to get full floating point accuracy

#define V_REF    2.54         //use the measured Aref voltage

//declare the variables used

volatile boolean doorOPEN = false;   //desired door state set to closed
byte rxbyte = 0;                     //rxbyte is the received byte from Smartie
byte temp = 0;
volatile unsigned long SWtime = 0;   //holds the time of the last valid switch push
float voltage1 = 0.0;                // calculated voltage for A0
float voltage2 = 0.0;                // calculated voltage for A1

LiquidCrystal lcd(rsPIN, enablePIN, d4PIN, d5PIN, d6PIN, d7PIN);
VarSpeedServo myServo; //create a servo object

void setup() {
  //set the pins to be ins or outs
  pinMode(LEDPIN, OUTPUT);
  digitalWrite(LEDPIN, LOW);            //turn LED off
  pinMode(servoPIN, OUTPUT);
  pinMode(SWitchPIN, INPUT_PULLUP);
  pinMode(redPIN, OUTPUT);
  pinMode(greenPIN, OUTPUT);
  pinMode(bluePIN, OUTPUT);

  attachInterrupt(1, SW_ISR, FALLING);

  Serial.begin(9600);

  lcd.begin(numCols, numRows);
  lcd.clear();

  analogWrite(bluePIN,0);                //Blue brightness 255-0
  analogWrite(redPIN,255);               //Red brightness 255-0
  analogWrite(greenPIN,255);             //Green brightness 255-0

  analogReference(INTERNAL);              //use the internal 2.56v ADC reference

  //CMD the servo to close the door
  myServo.attach(servoPIN);               // Attach the servo
  myServo.slowmove(posCloseCMD, fastSPD); // Tell servo to go to closed position
  
  //put a hello world on the LCD
  lcd.home();
  lcd.print("lcd smartie");
  lcd.setCursor(0, 1);
  lcd.print("arduino");
  lcd.setCursor(0, 2);
  lcd.print("Line 3");
  lcd.setCursor(0, 3);
  lcd.print("Line 4");
}


//the following function is the ISR that responds to the push button switch
//it commands the door to open or close at slow speed
void SW_ISR(){
  //debounce the switch by ignoring any interrupt that occurs too soon after the prior one
  unsigned long Time = millis();
  if(Time - SWtime > DBdelay){            //enough time has elapsed, not a switch bounce
    SWtime = Time;                        //save new time of switch push
    doorOPEN = !doorOPEN;                 //reverse desired door state
    if(doorOPEN == true){
      digitalWrite(LEDPIN, HIGH);         //turn LED on
      myServo.slowmove(posOpenCMD, slowSPD);    //tell servo to go to open position
    }
    else {
      digitalWrite(LEDPIN, LOW);          //turn LED off
      myServo.slowmove(posCloseCMD, slowSPD);   //tell servo to go to closed position
    }
  }
}


//this function is used by the smartie code to get data from the PC
byte serial_getch(){
  int incoming; 
  while (Serial.available()==0){
  }
  // read the incoming byte:
  incoming = Serial.read();
  return (byte) (incoming &0xff);
}


//the main loop is now just the hacked version of the Arduino Smartie code
void loop(){
  rxbyte = serial_getch();   //this calls the 'function' serial_getch(), stores result in rxbyte
  if (rxbyte == 254)     //Matrix uses 254 for commands, if rxbyte = 254 the the code below runs
  {
    switch (serial_getch())  //calls serial_getch() to get the next byte from the PC
    {
    case 66: //former backlight on command, now hacked to sample A0 and send voltage to LCD
      voltage1 = DIV_1 * float((analogRead(A0)) * V_REF/1023.0);   
      lcd.setCursor(0,2);
      lcd.print("CPU VCORE ");   
      lcd.print(voltage1, 3);
      lcd.print("v");
      break;
    case 70: //former backlight off command, now hacked to sample A1 and send voltage to LCD
      voltage2 = DIV_2 * float((analogRead(A1)) * V_REF/1023.0);
      lcd.setCursor(0,3);
      lcd.print("CPU VRIN ");
      lcd.print(voltage2, 3);
      lcd.print("v");
      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
}