I have a basic Atmega168p setup with arduino and using a MCP2221 for serial I/O. I had this working fine, but suddenly it's jibbing right out.
I also have a LCD displaying stuff and it goes completely nuts with junk, and the serial is just outputting lot of garbage. If I comment out the code block that starts with "if(cmdlevel==0)" then it works fine. If I change the values that it's looking for it does not matter either. I'm completely confused as to why it's acting this way, it was fine before. Maybe there's something I'm completely missing here, thanks in advance for the help.
/*
Solar power pack controller code
*/
// include the LCD library code:
#include <LiquidCrystal.h>
#include <EEPROM.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(4, 10, 9, 6, 7, 8); //RS, ENBL, D4, D5, D6, D7
int incomingByte = 0;
char serialbuffer[51];
int serialpos=0;
int cmdlevel=0; //command level. 0=main command, 1+ see command levels below
int cmdsublevel=0; //sub levels used within command functions
/* command levels :
1: callibration menu
2: float voltage adjust
*/
int lcddelayint=0; //used for LCD delay feature (to display something for extended time)
//pin assignments:
int PINsoftoff=2;
int PINbuckpwm=3;
int PINloadrelay=5;
int PINampspv=A3;
int PINampsload=A1;
int PINvoltspv=A4;
int PINvoltsload=A2;
//callibration vars: (nvram)
int nvram_solvolt;
int nvram_solamps;
int nvram_loavolt;
int nvram_loaamps;
void ConvNum(char * out, long num)
{
if(num<0)num=0;
if(num>9999999)num=9999999;
char numstrrev[8] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
char numstr[8];
long tempint=num;
int digits=0;
/*
9,999,999 = 999. 7d = 3 (comma pos)
999,999 = 99.9 6d = 2
10,000 = 1.00 5d = 1
1,000 = 0.10 4d = 1
100 = 0.01 3d = 1
10 = .001 2d = 0
0-9 = .000 1d = 0
*/
//convert num to char array (in reverse)
for(int i=0;i<8;i++)
{
int tmp = tempint%10;
numstrrev[i]=0x30+tmp;
//debug:
//cout<<i<<":"<<tmp<<" tempint:"<<tempint<<" numstrrev:"<<numstrrev<<endl;
tempint=tempint-tmp;
tempint=tempint/10;
digits++;
if(tempint==0)break;
}
//cout<<" digits:"<<digits<<endl;//debug
int pos=0;
if(digits<=1)
{
out[0]='.';
out[1]='0';
out[2]='0';
out[3]='0';
}
else if(digits==2)
{
out[0]='.';
out[1]='0';
out[2]='0';
out[3]=numstrrev[1];
}
else if(digits==3)
{
out[0]='0';
out[1]='.';
out[2]='0';
out[3]=numstrrev[2];
}
else if(digits==4)
{
out[0]='0';
out[1]='.';
out[2]=numstrrev[3];
out[3]=numstrrev[2];
}
else if(digits==5)
{
out[0]=numstrrev[4];
out[1]='.';
out[2]=numstrrev[3];
out[3]=numstrrev[2];
}
else if(digits==6)
{
out[0]=numstrrev[5];
out[1]=numstrrev[4];
out[2]='.';
out[3]=numstrrev[3];
}
else if(digits==7)
{
out[0]=numstrrev[6];
out[1]=numstrrev[5];
out[2]=numstrrev[4];
out[3]='.';
}
else
{
out[0]='9';
out[1]='9';
out[2]='9';
out[3]='.';
}
out[4]=0x0;
}
bool lcddelay(int setto)
{
if(setto>0)
{
lcddelayint=setto+(millis() / 1000);
return false;
}
if(lcddelayint>(millis() / 1000))return true;
return false;
}
void setup()
{
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
Serial.begin(9600); // set up Serial library at 9600 bps
pinMode(PINsoftoff, INPUT);
pinMode(PINbuckpwm, OUTPUT);
pinMode(PINloadrelay, OUTPUT);
}
void CMD_help()
{
Serial.print("\r\n\r\n-------------------------------------------------------------------------------\r\n");
Serial.print("Solar Power System [updated July 11 2016] - [url=http://www.iceteks.com\]www.iceteks.com\[/url]r\n");
Serial.print("-------------------------------------------------------------------------------\r\n");
Serial.print("help Show this screen\r\n");
Serial.print("pcloadletter Make the LCD say \"PC LOAD LETTER\"\r\n");
Serial.print("eeprompdump Dump contents of eeprom (NVRAM)\r\n");
Serial.print("cal volt/amp calibration\r\n");
}
void CMD_pcloadletter()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" PC LOAD LETTER ");
lcddelay(30);
}
void CMD_eepromdump()
{
int address=0;
byte value;
Serial.print("Dumping EEPROM...\r\n\r\n");
do
{
// read a byte from the current address of the EEPROM
value = EEPROM.read(address);
Serial.print(address);
Serial.print("\t");
Serial.print(value, DEC);
Serial.println();
/***
Advance to the next address, when at the end restart at the beginning.
Larger AVR processors have larger EEPROM sizes, E.g:
- Arduno Duemilanove: 512b EEPROM storage.
- Arduino Uno: 1kb EEPROM storage.
- Arduino Mega: 4kb EEPROM storage.
Rather than hard-coding the length, you should use the pre-provided length function.
This will make your code portable to all AVR processors.
***/
address = address + 1;
}while(address < 10);
Serial.print("\r\n\r\nDone.\r\n");
}
void CMD_cal()
{
/* int calvalue=0;
calvalue = Serial.read()+0x30;
if(calvalue<1 || calvalue>4)
{
Serial.print("Usage: cal [1-4] 1:sol volts, 2: sol amps, 3: load volts, 4: load amps\r\n");
}*/
/*
cmdsublevels:
0 = main menu
1 = solvolt
2 = solamps
3 = loavolt
4 = loaamps
*/
if(cmdsublevel==0)
{
if(serialpos<=0)
{
Serial.print("Callibration menu options:\r\n");
Serial.print("solvolt solar voltage\r\n");
Serial.print("solamps solar amps\r\n");
Serial.print("loavolt load voltage\r\n");
Serial.print("loaamps load amps voltage\r\n");
Serial.print("quit Quit this menu\r\n");
}
else if(strcmp("solvolt",serialbuffer)==0)cmdsublevel=1;
else if(strcmp("solamps",serialbuffer)==0)cmdsublevel=2;
else if(strcmp("loavolt",serialbuffer)==0)cmdsublevel=3;
else if(strcmp("loaamps",serialbuffer)==0)cmdsublevel=4;
else if(strcmp("quit",serialbuffer)==0)
{
cmdsublevel=0;
cmdlevel=0;
}
}
else if(cmdsublevel==1)
{
char tmpnum[10];
if(serialpos<=0)
{
Serial.print("solvolt current value: ");
itoa(nvram_solvolt,tmpnum,10);
Serial.print(tmpnum);
Serial.print("Enter new value:");
}
else
{
Serial.print("New value set to:");
Serial.print(serialbuffer);
}
}
}
void loop()
{
//analogWrite(PINbuckpwm, 120);
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
//lcd.setCursor(0, 1);
// print the number of seconds since reset:
// lcd.print(millis() / 1000);
//LCD display update:
//lcd.clear();
if(!lcddelay(0))
{
int num=0;
char numchar[5];
//Solar volts:
ConvNum(numchar,(long)analogRead(PINvoltspv)*100);
lcd.setCursor(0, 0);
lcd.print("SOL: ");
lcd.setCursor(5,0);
lcd.print(numchar);
lcd.setCursor(9,0);
lcd.print("V ");
//Solar amps:
ConvNum(numchar,(long)analogRead(PINampspv)*100);
lcd.setCursor(11,0);
lcd.print(numchar);
lcd.setCursor(15,0);
lcd.print("A");
//load volts:
ConvNum(numchar,(long)analogRead(PINvoltsload)*100);
lcd.setCursor(0, 1);
lcd.print("LOA: ");
lcd.setCursor(5,1);
lcd.print(numchar);
lcd.setCursor(9,1);
lcd.print("V ");
//load amps:
ConvNum(numchar,(long)analogRead(PINampsload)*100);
lcd.setCursor(11,1);
lcd.print(numchar);
lcd.setCursor(15,1);
lcd.print("A");
lcddelay(2);
}
// Handle Serial comm:
int stilltyping=true;
if (Serial.available() > 0)
{
// read the incoming byte:
incomingByte = Serial.read();
//filter unwanted chars:
if(incomingByte<13 || (incomingByte>14 && incomingByte<32) || incomingByte>126)return;
//echo back what we typed:
Serial.print((char)incomingByte);
//if enter pressed or reached end of buffer, process buffer
if(incomingByte==13 || serialpos>=49)
{
//Serial.print("\r\n");
stilltyping=false;
Serial.flush();
}
else
{
serialbuffer[serialpos]=incomingByte;
serialbuffer[serialpos+1]=0;
serialpos++;
}
}
//handle command:
if(!stilltyping)
{
if(cmdlevel==0) //if I comment out this block, then it acts fine.
{
if(strcmp("help",serialbuffer)==0)CMD_help();
else if(strcmp("pcloadletter",serialbuffer)==0)CMD_pcloadletter();
else if(strcmp("eepromdump",serialbuffer)==0)CMD_eepromdump();
else if(strcmp("cal",serialbuffer)==0)
{
cmdlevel=1;
}
else if(serialpos>0)
{
Serial.print("\r\nInvalid command: \"");
Serial.print(serialbuffer);
Serial.print("\", type help to see list of valid commands");
}
}
else if(cmdlevel==1)
{
CMD_cal();
}
//decide which cursor to show, # for master menu, > for within a command
if(cmdlevel==0)Serial.print("\r\n# ");
else Serial.print("\r\n> ");
//clear buffer
serialpos=0;
for(int i=0;i<51;i++)
{
serialbuffer[i]=0x0;
}
}
}