PDA

View Full Version : Read Alltrax serial with arduino and show on LCD



zerous
25 March 2016, 1636
Original from this thread (http://elmoto.net/showthread.php?t=4189)

In 2013, before I discovered there is something called HC Cycle Analyst :), for 3 month I used Arduino Mega to read out values from Alltrax Axe 7245 to show values on a 20x4 LCD screen.

6922


As I remeber it parts was :
- Arduino Mega. I discovered I need a lot of CPU power to handle UART communication and send information via SoftwareSerial to SerLCD.
- RS232 shield to connect arduino to Alltrax controller
- Serial Backpack for LCD https://www.sparkfun.com/products/258
- and 20x4 LCD screen simular this https://www.sparkfun.com/products/256


SimpleTimer is a library to launch timed actions.

Idea behind sketch is to ten times per second poll controller for voltage and current values, process received answer and update variables for Ah, voltage, current and Wh and to show those on LCD screen. If I update LCd screen every 100 ms it flicks a lot, so I update it every fourth reading.

An hour contain 36000 100 ms, so current value read out is devided by 36000. In theory if my motor use 50A for 1 hour every 100 ms read out should be 50A and if I divide it by 36000 and add every reading together I get 50Ah after 1 hour. :)

At now i do not have rs232 shield availabe and can not test it again.

Here is my code. I be happy if someone else can use too.



#include
<SimpleTimer.h>
#include
<SoftwareSerial.h>

// the timer object
SimpleTimer timer;

//initiate SerialBackpack backpack and LCD screen
#define txPin 7 //Pin 7 is one connected to SerialBackpack SerLCD
SoftwareSerial LCD = SoftwareSerial(0,txPin);

byte strValue[7];
unsigned long time;
unsigned long latest;


float Current = 0;
float Voltage = 0;
float Wh = 0;
float currentCounter = 0;
byte currentArray[7] = {
0x5B,0x04,0x60,0x00,0x00,0x00,0x41}; // output current
byte voltageArray[7] = {
0x5B,0x04,0x39,0x00,0x00,0x00,0x68}; // output voltage
int lcdOut = 0;

void setup()
{
Serial1.begin(9600);
pinMode(txPin, OUTPUT);
LCD.begin(9600);
backlightOn();
clearLCD();
timer.setInterval(100, repeatMe);
}

void loop()
{
timer.run();
}

void repeatMe() {
selectLineFour();

time = millis();
LCD.print(time - latest);
LCD.print(" ");
//Serial.println(time - senast);
latest = time;
lcdOut += 1; // Update LCD every 4th reading to avoid flimming
if( lcdOut == 4 ) {
lcdOut = 1;
}

Serial1.write(currentArray,7);// Ask AXE controller for current value

if(Serial1.available()) {
if(Serial1.peek() == 181) {// Does it start with B5?
for(int i=0;i<7;i++) { // If so, fill array strValue
strValue[i] = Serial1.read();
}

Current = ((strValue[4])*16*16)+(strValue[3]); //calculate current value
currentCounter += (Current/36000); // add value to AH counter
}
else // if B5 is not first char, empty buffer
{
while(Serial1.available()>0) // empty
{
Serial1.read(); // empty until there is nothing in buffer
}
}
}

Serial1.write(voltageArray,7);// Ask AXE controlelr about battery voltage
if(Serial1.available()) {// do we have a answer in serial port?
if(Serial1.peek() == 181) {// Does it start with B5?
for(int i=0;i<7;i++) { // If so fill array strValue
strValue[i] = Serial1.read();
}

Voltage = ((strValue[4])*16*16)+(strValue[3]); //calculate voltage value
Voltage = Voltage * 0.1025 ;
}
else // if B5 is not first char, empty buffer
{
while(Serial1.available()>0) // empty until it is empty
{
Serial1.read(); // read out until it empty
}
}
}

Wh += Voltage * (Current/36000);

if(lcdOut == 3) {
printValue(Current, 0); //Print out current value

}
if(lcdOut == 2) {
selectLineTwo();// choose line two on lcd
//LCDFloat(currentCounter,4);
LCDFloat(Voltage,3); // Print out voltage value with 2 decimals
delay(10);
LCD.print(" V ");
}
if(lcdOut == 1) {
selectLineThree();
LCDFloat(Wh,2);
LCD.print(" Wh of 4420 "); //4420 was my battery pack
}
//LCD.print(" Ah ");}
Current = 0; // does it need to be set to 0?
}

//LCD functions
void selectLineOne(){ //puts the cursor at line 0 char 0.
LCD.write(0xFE); //command flag
LCD.write(128); //position
}
void selectLineTwo(){ //puts the cursor at line 0 char 0.
LCD.write(0xFE); //command flag
LCD.write(192); //position
}
void selectLineThree(){ //puts the cursor at line 3 char 0.
LCD.write(0xFE); //command flag
LCD.write(148); //position
}
void selectLineFour(){ //puts the cursor at line 4 char 0.
LCD.write(0xFE); //command flag
LCD.write(212); //position
}
void goTo(int position) { //position = line 1: 0-19, line 2: 20-39, etc, 79+ defaults back to 0
if (position<20){
LCD.write(0xFE); //command flag
LCD.write((position+128)); //position
}
else if (position<40){
LCD.write(0xFE); //command flag
LCD.write((position+128+64-20)); //position
}
else if (position<60){
LCD.write(0xFE); //command flag
LCD.write((position+128+20-40)); //position
}
else if (position<80){
LCD.write(0xFE); //command flag
LCD.write((position+128+84-60)); //position
}
else {
goTo(0);
}
}
void clearLCD(){
LCD.write(0xFE); //command flag
LCD.write(0x01); //clear command.
}
void backlightOn(){ //turns on the backlight
LCD.write(0x7C); //command flag for backlight stuff
LCD.write(157); //light level.
}
void backlightOff(){ //turns off the backlight
LCD.write(0x7C); //command flag for backlight stuff
LCD.write(128); //light level for off.
}
void serCommand(){ //a general function to call the command flag for issuing all other commands
LCD.write(0xFE);
}

//Function to write out float values on LCD
//http://forum.arduino.cc/index.php?topic=46688.0

void LCDFloat(double number, int8_t digits) {
if (number == 0) {
LCD.print('0');
return;
}
if (number < 0) {
LCD.print('-');
number = -number;
} // handle negative numbers
int8_t e = log(number) * (1/log(10)); // determine exponent
if (digits > 7) digits = 7;
else if (digits < 1) digits = 1; // shape digits
if (number >= 1) digits--;
number += .5 * pow(10,e-digits); // rounding
// print out
if (e >= digits) {
e -= digits;
number *= pow(10,-e);
LCD.print((uint32_t)number);
for (; e>0; e--) LCD.print('0');
}
else {
const uint32_t I = (uint32_t) number;
number -= I;
LCD.print(I);
uint32_t F = (uint32_t) (number * pow(10,digits-e));
if (F == 0) return;
LCD.print('.');
for (; e<0; e++) LCD.print('0');
while (F % 10 == 0) F /= 10;
LCD.print(F);
}
}

void printValue(float value, int position) {
goTo(0);
if(value >99) {
LCDFloat(value, 3);
}
if(value >9 && value<100) {
LCD.print(" ");
LCDFloat(value, 2);
}
if(value <10) {
LCD.print(" ");
LCDFloat(value, 1);
}
delay(10);
LCD.print(" A ");
}

ElMotoMike
25 March 2016, 1807
Very cool.

I have been working on a GPS speedometer that would display info onto a 480x320 lcd screen via the Mega... but it also had a horrible flicker. After a few weeks of trying to find a fix, I upgraded to the Due because it will display without a flicker. Perhaps try that out?

This was the video that convinced me to upgrade.

https://www.youtube.com/watch?v=JXcVw8dwxPw