<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://calebneedscollege.com/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Falgsc-al</id>
	<title>Public Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="http://calebneedscollege.com/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Falgsc-al"/>
	<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php/Special:Contributions/Falgsc-al"/>
	<updated>2026-05-15T14:32:28Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.33.1</generator>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=132</id>
		<title>CAN bus battery monitor with 3.5&quot; TFT Touch screen on Arudino MEGA2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=132"/>
		<updated>2021-02-19T04:49:14Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */  BMS units changed due to suspected failure.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
This version trimmed off several bytes of RAM and provides additional speedup (approx 1ms per update)&lt;br /&gt;
Fixed voltage sum bug.&lt;br /&gt;
[[LCDWIKI Libraries]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;quot;mcp_can.h&amp;quot;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS 4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS 8     //Hazardous to modify&lt;br /&gt;
#define REFRESH 1000   //Refresh rate display&lt;br /&gt;
#define ALARM 3.660    //Alarm threshold&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x1863&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RED 1111 1000 0000 0000&lt;br /&gt;
//BLU 0000 0000 0001 1111&lt;br /&gt;
//GRE 0000 0111 1110 0000&lt;br /&gt;
//GRY 0001 1000 0110 0011 = 0x01863&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
int temperature[NUMPACKS][NUMCELLS];&lt;br /&gt;
&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000018, 0x00000020, 0x00000006, 0x00000012};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
&lt;br /&gt;
//unsigned char bufA[10];&lt;br /&gt;
//unsigned char buf0[10];&lt;br /&gt;
//unsigned char buf3[10];&lt;br /&gt;
//unsigned char buf5[10];&lt;br /&gt;
//unsigned char buf20[10];&lt;br /&gt;
//unsigned char buf21[10];&lt;br /&gt;
//unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
long st, fn;&lt;br /&gt;
int q;  &lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temperature[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);        &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    Serial.print(&amp;quot;p&amp;quot;);//packet received&lt;br /&gt;
&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temperature[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temperature[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temperature[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temperature[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temperature code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temperature code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        //for(int i = 0; i&amp;lt;len; i++) {buf3[i] = buf[i];}&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500) ;//{for(int i = 0; i&amp;lt;len; i++){buf5[i] = buf[i];}}&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00) ;//{for(int i = 0; i&amp;lt;len; i++){bufA[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000) ;//{for(int i = 0; i&amp;lt;len; i++){buf0[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][7] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][6] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][5] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf20[i] = buf[i];} &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][4] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][3] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][2] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf21[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][1] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][0] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf22[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
        //TestTemp();&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          sum[i]=0.0;&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
            sum[i] += voltage[i][j];&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)  buzzer=HIGH;&lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;&lt;br /&gt;
        &lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen(0);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode==0)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blues&lt;br /&gt;
    mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
    mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blacks&lt;br /&gt;
    mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,42 , 150, 191);   //Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,42 , 310, 191);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,234 , 150, 386);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170, 234 , 310, 386);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Lines&lt;br /&gt;
    mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
    mylcd.Draw_Line(11, 62, 149, 62);//Pack 1&lt;br /&gt;
    mylcd.Draw_Line(171, 62, 309, 62);//Pack 2&lt;br /&gt;
    mylcd.Draw_Line(11, 254, 149, 254);//Pack 3&lt;br /&gt;
    mylcd.Draw_Line(171, 254, 309, 254);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Reds &lt;br /&gt;
    mylcd.Set_Draw_color(RED);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,193 , 150, 214);//Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,193, 310, 214);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,384 , 150, 407);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170,384, 310, 407);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Set_Text_Mode(1);&lt;br /&gt;
    mylcd.Set_Text_Size(3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
&lt;br /&gt;
    mylcd.Set_Text_Size(2);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x18    (-)   x20    (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*10);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x06    (-)   x12    (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*22);&lt;br /&gt;
&lt;br /&gt;
    //credits, statusbar&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(int battery)&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(temperature[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
  &lt;br /&gt;
  if(c==7)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Set_Text_Mode(0);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
    mylcd.Print_Number_Float(sum[p], 3, xc+60, yc+22, '.', 0, ' ');&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  }&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw)&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit&lt;br /&gt;
  //Supports Rounding&lt;br /&gt;
  //if( (raw*1.555)-26.0 - (int) ((raw*1.555)-26.0) &amp;gt;= 0.5)&lt;br /&gt;
  //  return (int)((raw*1.555)-25.0);&lt;br /&gt;
  //else&lt;br /&gt;
  //  return (int)((raw*1.555)-26.0);&lt;br /&gt;
  short static const table[256] = &lt;br /&gt;
                     {-26, -24,-23,-21,-20,-18,-17,-15,-14,-12,-10,-9,-7,-6,-4,-3,-1,&lt;br /&gt;
                      0,2,4,5,7,8,10,11,13,14,16,18,19,21,22,24,25,27,28,30,32,33,35,&lt;br /&gt;
                      36,38,39,41,42,44,46,47,49,50,52,53,55,56,58,60,61,63,64,66,67,&lt;br /&gt;
                      69,70,72,74,75,77,78,80,81,83,84,86,88,89,91,92,94,95,97,98,100,&lt;br /&gt;
                      102,103,105,106,108,109,111,112,114,116,117,119,120,122,123,125,&lt;br /&gt;
                      126,128,130,131,133,134,136,137,139,140,142,143,145,147,148,150,&lt;br /&gt;
                      151,153,154,156,157,159,161,162,164,165,167,168,170,171,173,175,&lt;br /&gt;
                      176,178,179,181,182,184,185,187,189,190,192,193,195,196,198,199,&lt;br /&gt;
                      201,203,204,206,207,209,210,212,213,215,217,218,220,221,223,224,&lt;br /&gt;
                      226,227,229,231,232,234,235,237,238,240,241,243,245,246,248,249,&lt;br /&gt;
                      251,252,254,255,257,259,260,262,263,265,266,268,269,271,273,274,&lt;br /&gt;
                      276,277,279,280,282,283,285,287,288,290,291,293,294,296,297,299,&lt;br /&gt;
                      301,302,304,305,307,308,310,311,313,315,316,318,319,321,322,324,&lt;br /&gt;
                      325,327,329,330,332,333,335,336,338,339,341,343,344,346,347,349,&lt;br /&gt;
                      350,352,353,355,357,358,360,361,363,364,366,367,369,371};&lt;br /&gt;
  return (int)table[raw]; &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=101</id>
		<title>CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=101"/>
		<updated>2020-12-10T21:55:57Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */ Default mode created by shorting pin 22 to ground during boot, bug fixes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
This was developed to test communication to the EPEVER AN Solar controller from the Arduino&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;mcp_can.h&amp;gt;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library http://www.lcdwiki.com/3.5inch_Arduino_Display-UNO&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
#include &amp;lt;ModbusMaster.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS                4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS                8     //Hazardous to modify&lt;br /&gt;
#define REFRESH                 1000   //Refresh rate display&lt;br /&gt;
#define ALARM                   3.640    //Alarm threshold&lt;br /&gt;
#define LOWCELL                 3.100&lt;br /&gt;
#define windDown_period         600000 //Delay before controller attempts to increase the charge voltage, giving cells time to settle&lt;br /&gt;
#define windUp_period           60000&lt;br /&gt;
#define windUpThreshold         3.550 //WindUp function will not call again until a cell reaches this voltage&lt;br /&gt;
#define dischargeProtect_period 600000&lt;br /&gt;
#define defaultPin              22 //Short pin 22 to ground to send default values in the next group to the controller&lt;br /&gt;
&lt;br /&gt;
//Define the default values for your pack here, value *100, no decimal&lt;br /&gt;
#define def_BATT_TYPE           0000&lt;br /&gt;
#define def_BATT_AH             880&lt;br /&gt;
#define def_TEMP_COMP           300&lt;br /&gt;
#define def_OVERVOLT_DISC_VAL   2950&lt;br /&gt;
#define def_CHARGING_LIMIT_VAL  2860&lt;br /&gt;
#define def_OVERVOLT_RECON_VAL  2880&lt;br /&gt;
#define def_EQUILIBRIUM_CV_VAL  2830&lt;br /&gt;
#define def_BOOST_CV_VAL        2830&lt;br /&gt;
#define def_FLOAT_CV_VAL        2760        &lt;br /&gt;
#define def_BOOST_RECON_VAL     2640 &lt;br /&gt;
#define def_LOW_VOLT_RECON      2350&lt;br /&gt;
#define def_UNDERVOLT_RECOV     2440&lt;br /&gt;
#define def_UNDERVOLT_WARNING   2400&lt;br /&gt;
#define def_LOW_VOLT_DISC       2220&lt;br /&gt;
#define def_DISCHARGE_LIMIT     2120&lt;br /&gt;
#define dayLightVolt            3500  &lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x1863&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RS485 converter connections&lt;br /&gt;
#define MAX485_DE   49&lt;br /&gt;
#define MAX485_RE   48&lt;br /&gt;
&lt;br /&gt;
// For Epever AN controller MODBUS read&lt;br /&gt;
#define PANEL_VOLTS     0x00&lt;br /&gt;
#define PANEL_AMPS      0x01&lt;br /&gt;
#define PANEL_POWER_L   0x02&lt;br /&gt;
#define PANEL_POWER_H   0x03&lt;br /&gt;
#define BATT_VOLTS      0x04&lt;br /&gt;
#define BATT_AMPS       0x05&lt;br /&gt;
#define BATT_POWER_L    0x06&lt;br /&gt;
#define BATT_POWER_H    0x07&lt;br /&gt;
#define OVERVOLT_DISC   0x03&lt;br /&gt;
#define CHARGING_LIMIT  0x04&lt;br /&gt;
#define OVERVOLT_RECON  0x05&lt;br /&gt;
#define EQUILIBRIUM_CV  0x06&lt;br /&gt;
#define BOOST_CV        0x07&lt;br /&gt;
#define FLOAT_CV        0x08&lt;br /&gt;
#define BOOST_RECON     0x09&lt;br /&gt;
#define LOW_VOLT        0x0A&lt;br /&gt;
#define UNDERVOLT_RECOV 0x0B&lt;br /&gt;
#define UNDERVOLT_WARN  0x0C&lt;br /&gt;
#define LOW_VOLT_DISC   0x0D&lt;br /&gt;
#define DISCHARGE_LIMIT 0x0E&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = LOW;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
unsigned long currentMillis;&lt;br /&gt;
&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
int temperature[NUMPACKS][NUMCELLS];&lt;br /&gt;
&lt;br /&gt;
//Pack Parameters - you will fill this info in once you find the CAN address of your packs. Only the last two numbers will be relevant&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
float hotCellVolt = 0;&lt;br /&gt;
float coldCellVolt = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Variables for holding the solar controller's set values&lt;br /&gt;
unsigned short OVERVOLT_DISC_READ;&lt;br /&gt;
unsigned short CHARGING_LIMIT_READ;&lt;br /&gt;
unsigned short OVERVOLT_RECON_READ;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_READ;&lt;br /&gt;
unsigned short BOOST_CV_READ;&lt;br /&gt;
unsigned short FLOAT_CV_READ;&lt;br /&gt;
unsigned short BOOST_RECON_READ;&lt;br /&gt;
unsigned short LOW_VOLT_RECON_READ;&lt;br /&gt;
unsigned short UNDERVOLT_RECOVERY_READ;&lt;br /&gt;
unsigned short UNDERVOLT_WARNING_READ;&lt;br /&gt;
unsigned short LOW_VOLT_DISC_READ;&lt;br /&gt;
unsigned short DISCHARGE_LIMIT_READ;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding register values from the controller&lt;br /&gt;
unsigned short PANEL_VOLTS_READ;&lt;br /&gt;
unsigned short PANEL_AMPS_READ;&lt;br /&gt;
unsigned short BATT_VOLTS_READ;&lt;br /&gt;
unsigned short BATT_AMPS_READ;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding values to be sent to the solar controller&lt;br /&gt;
unsigned short OVERVOLT_DISC_SETTO;&lt;br /&gt;
unsigned short CHARGING_LIMIT_SETTO;&lt;br /&gt;
unsigned short OVERVOLT_RECON_SETTO;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_CV_SETTO;&lt;br /&gt;
unsigned short FLOAT_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_RECON_SETTO;&lt;br /&gt;
unsigned short LOW_VOLT_RECON_SETTO;&lt;br /&gt;
unsigned short UNDERVOLT_RECOVERY_SETTO;&lt;br /&gt;
unsigned short UNDERVOLT_WARNING_SETTO;&lt;br /&gt;
unsigned short LOW_VOLT_DISC_SETTO;&lt;br /&gt;
unsigned short DISCHARGE_LIMIT_SETTO;&lt;br /&gt;
&lt;br /&gt;
//Variables for working with the controller&lt;br /&gt;
bool windDownFlag = LOW;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
&lt;br /&gt;
//Low failure rate timer&lt;br /&gt;
//const int windDown_period = 60000;&lt;br /&gt;
unsigned long windDown_etime = 0;&lt;br /&gt;
//const long windUp_period = 600000;&lt;br /&gt;
unsigned long windUp_etime = 0;&lt;br /&gt;
unsigned long dischargeProtect_etime = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(53);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
// instantiate ModbusMaster object&lt;br /&gt;
ModbusMaster node;&lt;br /&gt;
&lt;br /&gt;
/*Function Prototypes&lt;br /&gt;
void BuildScreen(int);&lt;br /&gt;
void UpdateScreen(int);&lt;br /&gt;
void preTransmission();&lt;br /&gt;
void postTransmission();&lt;br /&gt;
void getControllerParams();&lt;br /&gt;
void windDown();&lt;br /&gt;
void windUp();&lt;br /&gt;
void dischargeProtect();&lt;br /&gt;
void updateController();&lt;br /&gt;
void defaultController();&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
long st, fn;&lt;br /&gt;
int q;  &lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.print(&amp;quot;My LCD ID: &amp;quot;);&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temperature[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  pinMode(MAX485_RE, OUTPUT);&lt;br /&gt;
  pinMode(MAX485_DE, OUTPUT);&lt;br /&gt;
  // Init in receive mode&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
  &lt;br /&gt;
  // Modbus setup at 115200 baud&lt;br /&gt;
  Serial1.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  // EPEver Device ID 1&lt;br /&gt;
  node.begin(1, Serial1);&lt;br /&gt;
&lt;br /&gt;
  // Callbacks&lt;br /&gt;
  node.preTransmission(preTransmission);&lt;br /&gt;
  node.postTransmission(postTransmission);&lt;br /&gt;
&lt;br /&gt;
  pinMode(defaultPin, INPUT_PULLUP);&lt;br /&gt;
  if (defaultPin == LOW)&lt;br /&gt;
    defaultController(); //Pin 22, shorted to ground, will default the controller to the settings defined atop&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Controller probed for default values&amp;quot;);&lt;br /&gt;
    getControllerParams();&lt;br /&gt;
    //This will read the stores values from the non volatile memory in the controller in the event of a reset.&lt;br /&gt;
    OVERVOLT_DISC_SETTO = OVERVOLT_DISC_READ;&lt;br /&gt;
    CHARGING_LIMIT_SETTO = CHARGING_LIMIT_READ;&lt;br /&gt;
    OVERVOLT_RECON_SETTO = OVERVOLT_RECON_READ;&lt;br /&gt;
    EQUILIBRIUM_CV_SETTO = EQUILIBRIUM_CV_READ;&lt;br /&gt;
    BOOST_CV_SETTO = BOOST_CV_READ;&lt;br /&gt;
    FLOAT_CV_SETTO = FLOAT_CV_READ;&lt;br /&gt;
    BOOST_RECON_SETTO = BOOST_RECON_READ;&lt;br /&gt;
    LOW_VOLT_RECON_SETTO = LOW_VOLT_RECON_READ;&lt;br /&gt;
    UNDERVOLT_RECOVERY_SETTO = UNDERVOLT_RECOVERY_READ;&lt;br /&gt;
    UNDERVOLT_WARNING_SETTO = UNDERVOLT_WARNING_READ;&lt;br /&gt;
    LOW_VOLT_DISC_SETTO = LOW_VOLT_DISC_READ;&lt;br /&gt;
    DISCHARGE_LIMIT_SETTO = DISCHARGE_LIMIT_READ;&lt;br /&gt;
    Serial.println(&amp;quot;Default values pulled from controller&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);        &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    //Serial.print(&amp;quot;p&amp;quot;);//packet received&lt;br /&gt;
&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temperature[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temperature[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temperature[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temperature[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temperature code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temperature code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        //for(int i = 0; i&amp;lt;len; i++) {buf3[i] = buf[i];}&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500) ;//{for(int i = 0; i&amp;lt;len; i++){buf5[i] = buf[i];}}&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00) ;//{for(int i = 0; i&amp;lt;len; i++){bufA[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000) ;//{for(int i = 0; i&amp;lt;len; i++){buf0[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][7] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][6] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][5] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf20[i] = buf[i];} &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][4] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][3] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][2] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf21[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][1] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][0] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf22[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      hotCellVolt = voltage[0][0];&lt;br /&gt;
      coldCellVolt = voltage[0][0];&lt;br /&gt;
      for(int i=0; i&amp;lt;NUMPACKS;i++) //Calculate a pack sum and check for hot cells&lt;br /&gt;
      {&lt;br /&gt;
        sum[i]=0.0;&lt;br /&gt;
        for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
        {&lt;br /&gt;
          sum[i] += voltage[i][j];&lt;br /&gt;
          if (voltage[i][j] &amp;gt; hotCellVolt)&lt;br /&gt;
            hotCellVolt = voltage[i][j];&lt;br /&gt;
          else if (voltage[i][j] &amp;lt; coldCellVolt)&lt;br /&gt;
            coldCellVolt = voltage[i][j];&lt;br /&gt;
          if(hotCellVolt &amp;gt;= ALARM)&lt;br /&gt;
          {&lt;br /&gt;
            buzzer=HIGH;&lt;br /&gt;
          }&lt;br /&gt;
          if((coldCellVolt &amp;lt;= LOWCELL) &amp;amp;&amp;amp; (coldCellVolt &amp;gt;= 1))&lt;br /&gt;
          {&lt;br /&gt;
            dischargeProtect();&lt;br /&gt;
          }&lt;br /&gt;
          &lt;br /&gt;
        }  &lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
        &lt;br /&gt;
      //Execute alarm condition&lt;br /&gt;
      currentMillis = millis();&lt;br /&gt;
      if(buzzer)&lt;br /&gt;
      {&lt;br /&gt;
        digitalWrite(49,1);&lt;br /&gt;
        windDown(); // This loop should only be executed once and then skipped for at least 1 minute&lt;br /&gt;
        windDown_etime = currentMillis;&lt;br /&gt;
        Serial.println(&amp;quot;Buzzer Loop&amp;quot;);&lt;br /&gt;
      } else digitalWrite(49,0);        &lt;br /&gt;
      if (windDownFlag &amp;amp;&amp;amp; ((unsigned long)(currentMillis - windDown_etime) &amp;gt;= windDown_period))&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;post windDown windUp triggered&amp;quot;);&lt;br /&gt;
          windUp();&lt;br /&gt;
          windUp_etime = currentMillis;&lt;br /&gt;
        }&lt;br /&gt;
      if ((PANEL_VOLTS_READ &amp;gt;= dayLightVolt) &amp;amp;&amp;amp; (PANEL_AMPS_READ &amp;lt;= 1) &amp;amp;&amp;amp; (hotCellVolt &amp;lt;= windUpThreshold) &amp;amp;&amp;amp; ((unsigned long)(currentMillis - windUp_etime) &amp;gt;= windUp_period)) //Keep tweaking the controller to max&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;conditional windUp triggered&amp;quot;);&lt;br /&gt;
          windUp();&lt;br /&gt;
          windUp_etime = currentMillis;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
      if(unknownId != 0)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
        Serial.print(unknownId, HEX);&lt;br /&gt;
        Serial.println();&lt;br /&gt;
      }&lt;br /&gt;
     }&lt;br /&gt;
     else skip=LOW;    &lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      UpdateScreen(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode==0)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blues&lt;br /&gt;
    mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
    mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blacks&lt;br /&gt;
    mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,42 , 150, 191);   //Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,42 , 310, 191);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,234 , 150, 386);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170, 234 , 310, 386);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Lines&lt;br /&gt;
    mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
    mylcd.Draw_Line(11, 62, 149, 62);//Pack 1&lt;br /&gt;
    mylcd.Draw_Line(171, 62, 309, 62);//Pack 2&lt;br /&gt;
    mylcd.Draw_Line(11, 254, 149, 254);//Pack 3&lt;br /&gt;
    mylcd.Draw_Line(171, 254, 309, 254);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Reds &lt;br /&gt;
    mylcd.Set_Draw_color(RED);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,193 , 150, 214);//Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,193, 310, 214);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,384 , 150, 407);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170,384, 310, 407);//Pack 4&lt;br /&gt;
    //Title&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Set_Text_Mode(1);&lt;br /&gt;
    mylcd.Set_Text_Size(3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
    //Outline the screen&lt;br /&gt;
    mylcd.Set_Text_Size(2);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x04    (-)   x20    (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*10);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x06    (-)   x22    (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*22);&lt;br /&gt;
&lt;br /&gt;
    //credits, statusbar&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(int battery)&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(temperature[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
  &lt;br /&gt;
  if(c==7)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Set_Text_Mode(0);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
    mylcd.Print_Number_Float(sum[p], 3, xc+48, yc+22, '.', 0, ' ');&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  }&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw) // Convert the readings from the ADC to human readable&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit this loop will calculate it live but the look up table saves clock cycles&lt;br /&gt;
  //Supports Rounding&lt;br /&gt;
  //if( (raw*1.555)-26.0 - (int) ((raw*1.555)-26.0) &amp;gt;= 0.5)&lt;br /&gt;
  //  return (int)((raw*1.555)-25.0);&lt;br /&gt;
  //else&lt;br /&gt;
  //  return (int)((raw*1.555)-26.0);&lt;br /&gt;
  short static const table[256] = &lt;br /&gt;
                     {-26, -24,-23,-21,-20,-18,-17,-15,-14,-12,-10,-9,-7,-6,-4,-3,-1,&lt;br /&gt;
                      0,2,4,5,7,8,10,11,13,14,16,18,19,21,22,24,25,27,28,30,32,33,35,&lt;br /&gt;
                      36,38,39,41,42,44,46,47,49,50,52,53,55,56,58,60,61,63,64,66,67,&lt;br /&gt;
                      69,70,72,74,75,77,78,80,81,83,84,86,88,89,91,92,94,95,97,98,100,&lt;br /&gt;
                      102,103,105,106,108,109,111,112,114,116,117,119,120,122,123,125,&lt;br /&gt;
                      126,128,130,131,133,134,136,137,139,140,142,143,145,147,148,150,&lt;br /&gt;
                      151,153,154,156,157,159,161,162,164,165,167,168,170,171,173,175,&lt;br /&gt;
                      176,178,179,181,182,184,185,187,189,190,192,193,195,196,198,199,&lt;br /&gt;
                      201,203,204,206,207,209,210,212,213,215,217,218,220,221,223,224,&lt;br /&gt;
                      226,227,229,231,232,234,235,237,238,240,241,243,245,246,248,249,&lt;br /&gt;
                      251,252,254,255,257,259,260,262,263,265,266,268,269,271,273,274,&lt;br /&gt;
                      276,277,279,280,282,283,285,287,288,290,291,293,294,296,297,299,&lt;br /&gt;
                      301,302,304,305,307,308,310,311,313,315,316,318,319,321,322,324,&lt;br /&gt;
                      325,327,329,330,332,333,335,336,338,339,341,343,344,346,347,349,&lt;br /&gt;
                      350,352,353,355,357,358,360,361,363,364,366,367,369,371};&lt;br /&gt;
  return (int)table[raw]; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preTransmission() //Put RS485 into transmit mode by bringing the transmit and receive pins high&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 1);&lt;br /&gt;
  digitalWrite(MAX485_DE, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void postTransmission() //Put the RS485 into receive mode by bringing the transmit and receive pins low&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
}&lt;br /&gt;
void getControllerParams() // Hit the controller with a request for information&lt;br /&gt;
{&lt;br /&gt;
uint8_t result;&lt;br /&gt;
&lt;br /&gt;
  // Read input registers from the controller starting at address 0x3100)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readInputRegisters(0x3100, 5);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    PANEL_VOLTS_READ = node.getResponseBuffer(PANEL_VOLTS); //Data slot 0&lt;br /&gt;
    PANEL_AMPS_READ = node.getResponseBuffer(PANEL_AMPS); //Data slot 1&lt;br /&gt;
    BATT_VOLTS_READ = node.getResponseBuffer(BATT_VOLTS); //Data slot 4 (2,3 skipped, not needed)&lt;br /&gt;
    Serial.print(&amp;quot;Panel volts: &amp;quot;);&lt;br /&gt;
    Serial.println((float)PANEL_VOLTS_READ/100.00);&lt;br /&gt;
    Serial.print(&amp;quot;Panel Amps: &amp;quot;);&lt;br /&gt;
    Serial.println((float)PANEL_AMPS_READ/100.00);&lt;br /&gt;
    Serial.print(&amp;quot;Battery volts: &amp;quot;);&lt;br /&gt;
    Serial.println((float)BATT_VOLTS_READ/100.00);&lt;br /&gt;
    Serial.println();&lt;br /&gt;
  } &lt;br /&gt;
  else { //If there's an error send it to the console&lt;br /&gt;
    Serial.print(&amp;quot;Reading controller parameters failed, error:&amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
  //delay(1000);&lt;br /&gt;
&lt;br /&gt;
  // Read charging parameters from the controller starting at address 0x9000)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readHoldingRegisters(0x9000, 15);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    //Some values are not collected because we will always use the defaults&lt;br /&gt;
    OVERVOLT_DISC_READ = node.getResponseBuffer(OVERVOLT_DISC);&lt;br /&gt;
    CHARGING_LIMIT_READ = node.getResponseBuffer(CHARGING_LIMIT);&lt;br /&gt;
    OVERVOLT_RECON_READ = node.getResponseBuffer(OVERVOLT_RECON);&lt;br /&gt;
    EQUILIBRIUM_CV_READ = node.getResponseBuffer(EQUILIBRIUM_CV);&lt;br /&gt;
    BOOST_CV_READ = node.getResponseBuffer(BOOST_CV);&lt;br /&gt;
    FLOAT_CV_READ = node.getResponseBuffer(FLOAT_CV);&lt;br /&gt;
    BOOST_RECON_READ = node.getResponseBuffer(BOOST_RECON);&lt;br /&gt;
    LOW_VOLT_RECON_READ = node.getResponseBuffer(LOW_VOLT);&lt;br /&gt;
    UNDERVOLT_RECOVERY_READ = node.getResponseBuffer(UNDERVOLT_RECOV);&lt;br /&gt;
    UNDERVOLT_WARNING_READ = node.getResponseBuffer(UNDERVOLT_WARN);&lt;br /&gt;
    LOW_VOLT_DISC_READ = node.getResponseBuffer(LOW_VOLT_DISC);&lt;br /&gt;
    DISCHARGE_LIMIT_READ = node.getResponseBuffer(DISCHARGE_LIMIT);&lt;br /&gt;
    Serial.println(&amp;quot;Parameters received successfully&amp;quot;);&lt;br /&gt;
  } &lt;br /&gt;
  else {&lt;br /&gt;
    Serial.print(&amp;quot;The charging parameters failed to read, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //delay(2000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void windDown() // Bring the controller charge voltage down so the hot cell will kalm&lt;br /&gt;
{&lt;br /&gt;
  OVERVOLT_DISC_SETTO = BATT_VOLTS_READ + 50;&lt;br /&gt;
  CHARGING_LIMIT_SETTO = BATT_VOLTS_READ - 20;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  BOOST_CV_SETTO = BATT_VOLTS_READ - 40;&lt;br /&gt;
  FLOAT_CV_SETTO = BATT_VOLTS_READ - 50;&lt;br /&gt;
  BOOST_RECON_SETTO = BATT_VOLTS_READ - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
  windDownFlag = HIGH;&lt;br /&gt;
  Serial.println(&amp;quot;Wind down has been prepared for sending&amp;quot;);&lt;br /&gt;
  //Insert a timer to wind up in 2 minutes&lt;br /&gt;
}&lt;br /&gt;
void windUp() // Bring the controller charge voltage as close to max as possible&lt;br /&gt;
{&lt;br /&gt;
  Serial.println(&amp;quot;Windup activated&amp;quot;);&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  unsigned short difference = int((ALARM - hotCellVolt) * 100);&lt;br /&gt;
  unsigned short setvolt = BATT_VOLTS_READ + difference;&lt;br /&gt;
  if (difference &amp;gt; 10)&lt;br /&gt;
  {&lt;br /&gt;
    OVERVOLT_DISC_SETTO = (setvolt + 50);&lt;br /&gt;
    CHARGING_LIMIT_SETTO = setvolt;&lt;br /&gt;
    OVERVOLT_RECON_SETTO = setvolt - 10;&lt;br /&gt;
    EQUILIBRIUM_CV_SETTO = setvolt - 20;&lt;br /&gt;
    BOOST_CV_SETTO = setvolt - 30;&lt;br /&gt;
    FLOAT_CV_SETTO = setvolt - 40;&lt;br /&gt;
    BOOST_RECON_SETTO = setvolt - 100;&lt;br /&gt;
    Serial.println(&amp;quot;Wind Up has been prepared for sending&amp;quot;);&lt;br /&gt;
    updateController();&lt;br /&gt;
    windDownFlag = LOW;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
void dischargeProtect()&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  currentMillis = millis();&lt;br /&gt;
  if (((DISCHARGE_LIMIT_READ + 60) &amp;gt; BATT_VOLTS_READ) &amp;amp;&amp;amp; (unsigned long)(currentMillis - dischargeProtect_etime) &amp;gt;= dischargeProtect_period)&lt;br /&gt;
  {&lt;br /&gt;
    UNDERVOLT_RECOVERY_SETTO = BATT_VOLTS_READ + 50;&lt;br /&gt;
    UNDERVOLT_WARNING_SETTO = BATT_VOLTS_READ + 30;&lt;br /&gt;
    LOW_VOLT_RECON_SETTO = BATT_VOLTS_READ + 20;&lt;br /&gt;
    LOW_VOLT_DISC_SETTO = BATT_VOLTS_READ - 20;&lt;br /&gt;
    DISCHARGE_LIMIT_SETTO = BATT_VOLTS_READ - 50;&lt;br /&gt;
    Serial.println(&amp;quot;Overdischarge protection adjustment prepared&amp;quot;);&lt;br /&gt;
    updateController();&lt;br /&gt;
    dischargeProtect_etime = currentMillis;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
void updateController() // Send new information to the controller. Something unusual discovered with the Epever AN controller is that it will not change 9003-9007 &lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  node.clearTransmitBuffer(); //Prepare the buffer with new data, clear and fill&lt;br /&gt;
  node.setTransmitBuffer(0, def_BATT_TYPE);&lt;br /&gt;
  node.setTransmitBuffer(1, def_BATT_AH);&lt;br /&gt;
  node.setTransmitBuffer(2, def_TEMP_COMP);&lt;br /&gt;
  node.setTransmitBuffer(3, OVERVOLT_DISC_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(4, CHARGING_LIMIT_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(5, OVERVOLT_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(6, EQUILIBRIUM_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(7, BOOST_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(8, FLOAT_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(9, BOOST_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(10, LOW_VOLT_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(11, UNDERVOLT_RECOVERY_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(12, UNDERVOLT_WARNING_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(13, LOW_VOLT_DISC_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(14, DISCHARGE_LIMIT_SETTO);&lt;br /&gt;
  &lt;br /&gt;
  int result = (node.writeMultipleRegisters(0x9000,15)); //Yeet this new info to the controller&lt;br /&gt;
  if (result == 0) //Verify&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameters 9000-900F changed sucessfully&amp;quot;); // For Diagnostic console&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameters 9000-900F change failed, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
void defaultController()&lt;br /&gt;
{&lt;br /&gt;
  node.clearTransmitBuffer(); //Prepare the buffer with new data, clear and fill&lt;br /&gt;
  node.setTransmitBuffer(0, def_BATT_TYPE);&lt;br /&gt;
  node.setTransmitBuffer(1, def_BATT_AH);&lt;br /&gt;
  node.setTransmitBuffer(2, def_TEMP_COMP);&lt;br /&gt;
  node.setTransmitBuffer(3, def_OVERVOLT_DISC_VAL);&lt;br /&gt;
  node.setTransmitBuffer(4, def_CHARGING_LIMIT_VAL);&lt;br /&gt;
  node.setTransmitBuffer(5, def_OVERVOLT_RECON_VAL);&lt;br /&gt;
  node.setTransmitBuffer(6, def_EQUILIBRIUM_CV_VAL);&lt;br /&gt;
  node.setTransmitBuffer(7, def_BOOST_CV_VAL);&lt;br /&gt;
  node.setTransmitBuffer(8, def_FLOAT_CV_VAL);&lt;br /&gt;
  node.setTransmitBuffer(9, def_BOOST_RECON_VAL);&lt;br /&gt;
  node.setTransmitBuffer(10, def_LOW_VOLT_RECON);&lt;br /&gt;
  node.setTransmitBuffer(11, def_UNDERVOLT_RECOV);&lt;br /&gt;
  node.setTransmitBuffer(12, def_UNDERVOLT_WARNING);&lt;br /&gt;
  node.setTransmitBuffer(13, def_LOW_VOLT_DISC);&lt;br /&gt;
  node.setTransmitBuffer(14, def_DISCHARGE_LIMIT);&lt;br /&gt;
  &lt;br /&gt;
  int result = (node.writeMultipleRegisters(0x9000,15)); //Yeet this new info to the controller&lt;br /&gt;
  if (result == 0) //Verify&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameters 9000-900F have been set to default&amp;quot;); // For Diagnostic console&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameters 9000-900F default failed, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=100</id>
		<title>CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=100"/>
		<updated>2020-12-10T20:27:39Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
This was developed to test communication to the EPEVER AN Solar controller from the Arduino&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;mcp_can.h&amp;gt;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library http://www.lcdwiki.com/3.5inch_Arduino_Display-UNO&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
#include &amp;lt;ModbusMaster.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS                4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS                8     //Hazardous to modify&lt;br /&gt;
#define REFRESH                 1000   //Refresh rate display&lt;br /&gt;
#define ALARM                   3.640    //Alarm threshold&lt;br /&gt;
#define LOWCELL                 3.100&lt;br /&gt;
#define windDown_period         600000 //Delay before controller attempts to increase the charge voltage, giving cells time to settle&lt;br /&gt;
#define windUp_period           60000&lt;br /&gt;
#define windUpThreshold         3.550 //WindUp function will not call again until a cell reaches this voltage&lt;br /&gt;
#define dischargeProtect_period 600000&lt;br /&gt;
&lt;br /&gt;
//Define the default values for your pack here, value *100, no decimal&lt;br /&gt;
#define def_BATT_TYPE           0000&lt;br /&gt;
#define def_BATT_AH             880&lt;br /&gt;
#define def_TEMP_COMP           300&lt;br /&gt;
#define def_OVERVOLT_DISC_VAL   2950&lt;br /&gt;
#define def_CHARGING_LIMIT_VAL  2860&lt;br /&gt;
#define def_OVERVOLT_RECON_VAL  2880&lt;br /&gt;
#define def_EQUILIBRIUM_CV_VAL  2830&lt;br /&gt;
#define def_BOOST_CV_VAL        2830&lt;br /&gt;
#define def_FLOAT_CV_VAL        2760        &lt;br /&gt;
#define def_BOOST_RECON_VAL     2640 &lt;br /&gt;
#define def_LOW_VOLT_RECON      2350&lt;br /&gt;
#define def_UNDERVOLT_RECOV     2440&lt;br /&gt;
#define def_UNDERVOLT_WARNING   2400&lt;br /&gt;
#define def_LOW_VOLT_DISC       2220&lt;br /&gt;
#define def_DISCHARGE_LIMIT     2120&lt;br /&gt;
#define dayLightVolt            3500  &lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x1863&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RS485 converter connections&lt;br /&gt;
#define MAX485_DE   49&lt;br /&gt;
#define MAX485_RE   48&lt;br /&gt;
&lt;br /&gt;
// For Epever AN controller MODBUS read&lt;br /&gt;
#define PANEL_VOLTS     0x00&lt;br /&gt;
#define PANEL_AMPS      0x01&lt;br /&gt;
#define PANEL_POWER_L   0x02&lt;br /&gt;
#define PANEL_POWER_H   0x03&lt;br /&gt;
#define BATT_VOLTS      0x04&lt;br /&gt;
#define BATT_AMPS       0x05&lt;br /&gt;
#define BATT_POWER_L    0x06&lt;br /&gt;
#define BATT_POWER_H    0x07&lt;br /&gt;
#define OVERVOLT_DISC   0x03&lt;br /&gt;
#define CHARGING_LIMIT  0x04&lt;br /&gt;
#define OVERVOLT_RECON  0x05&lt;br /&gt;
#define EQUILIBRIUM_CV  0x06&lt;br /&gt;
#define BOOST_CV        0x07&lt;br /&gt;
#define FLOAT_CV        0x08&lt;br /&gt;
#define BOOST_RECON     0x09&lt;br /&gt;
#define LOW_VOLT        0x0A&lt;br /&gt;
#define UNDERVOLT_RECOV 0x0B&lt;br /&gt;
#define UNDERVOLT_WARN  0x0C&lt;br /&gt;
#define LOW_VOLT_DISC   0x0D&lt;br /&gt;
#define DISCHARGE_LIMIT 0x0E&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = LOW;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
unsigned long currentMillis;&lt;br /&gt;
&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
int temperature[NUMPACKS][NUMCELLS];&lt;br /&gt;
&lt;br /&gt;
//Pack Parameters - you will fill this info in once you find the CAN address of your packs. Only the last two numbers will be relevant&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
float hotCellVolt = 0;&lt;br /&gt;
float coldCellVolt = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Variables for holding the solar controller's set values&lt;br /&gt;
unsigned short OVERVOLT_DISC_READ;&lt;br /&gt;
unsigned short CHARGING_LIMIT_READ;&lt;br /&gt;
unsigned short OVERVOLT_RECON_READ;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_READ;&lt;br /&gt;
unsigned short BOOST_CV_READ;&lt;br /&gt;
unsigned short FLOAT_CV_READ;&lt;br /&gt;
unsigned short BOOST_RECON_READ;&lt;br /&gt;
unsigned short LOW_VOLT_RECON_READ;&lt;br /&gt;
unsigned short UNDERVOLT_RECOVERY_READ;&lt;br /&gt;
unsigned short UNDERVOLT_WARNING_READ;&lt;br /&gt;
unsigned short LOW_VOLT_DISC_READ;&lt;br /&gt;
unsigned short DISCHARGE_LIMIT_READ;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding register values from the controller&lt;br /&gt;
unsigned short PANEL_VOLTS_READ;&lt;br /&gt;
unsigned short PANEL_AMPS_READ;&lt;br /&gt;
unsigned short BATT_VOLTS_READ;&lt;br /&gt;
unsigned short BATT_AMPS_READ;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding values to be sent to the solar controller&lt;br /&gt;
unsigned short OVERVOLT_DISC_SETTO;&lt;br /&gt;
unsigned short CHARGING_LIMIT_SETTO;&lt;br /&gt;
unsigned short OVERVOLT_RECON_SETTO;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_CV_SETTO;&lt;br /&gt;
unsigned short FLOAT_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_RECON_SETTO;&lt;br /&gt;
unsigned short LOW_VOLT_RECON_SETTO;&lt;br /&gt;
unsigned short UNDERVOLT_RECOVERY_SETTO;&lt;br /&gt;
unsigned short UNDERVOLT_WARNING_SETTO;&lt;br /&gt;
unsigned short LOW_VOLT_DISC_SETTO;&lt;br /&gt;
unsigned short DISCHARGE_LIMIT_SETTO;&lt;br /&gt;
&lt;br /&gt;
//Variables for working with the controller&lt;br /&gt;
bool windDownFlag = LOW;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
&lt;br /&gt;
//Low failure rate timer&lt;br /&gt;
//const int windDown_period = 60000;&lt;br /&gt;
unsigned long windDown_etime = 0;&lt;br /&gt;
//const long windUp_period = 600000;&lt;br /&gt;
unsigned long windUp_etime = 0;&lt;br /&gt;
unsigned long dischargeProtect_etime = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(53);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
// instantiate ModbusMaster object&lt;br /&gt;
ModbusMaster node;&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
long st, fn;&lt;br /&gt;
int q;  &lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.print(&amp;quot;My LCD ID: &amp;quot;);&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temperature[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  pinMode(MAX485_RE, OUTPUT);&lt;br /&gt;
  pinMode(MAX485_DE, OUTPUT);&lt;br /&gt;
  // Init in receive mode&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
  &lt;br /&gt;
  // Modbus setup at 115200 baud&lt;br /&gt;
  Serial1.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  // EPEver Device ID 1&lt;br /&gt;
  node.begin(1, Serial1);&lt;br /&gt;
&lt;br /&gt;
  // Callbacks&lt;br /&gt;
  node.preTransmission(preTransmission);&lt;br /&gt;
  node.postTransmission(postTransmission);&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);        &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    //Serial.print(&amp;quot;p&amp;quot;);//packet received&lt;br /&gt;
&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temperature[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temperature[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temperature[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temperature[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temperature code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temperature code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        //for(int i = 0; i&amp;lt;len; i++) {buf3[i] = buf[i];}&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500) ;//{for(int i = 0; i&amp;lt;len; i++){buf5[i] = buf[i];}}&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00) ;//{for(int i = 0; i&amp;lt;len; i++){bufA[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000) ;//{for(int i = 0; i&amp;lt;len; i++){buf0[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][7] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][6] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][5] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf20[i] = buf[i];} &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][4] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][3] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][2] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf21[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][1] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][0] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf22[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      hotCellVolt = voltage[0][0];&lt;br /&gt;
      coldCellVolt = voltage[0][0];&lt;br /&gt;
      for(int i=0; i&amp;lt;NUMPACKS;i++) //Calculate a pack sum and check for hot cells&lt;br /&gt;
      {&lt;br /&gt;
        sum[i]=0.0;&lt;br /&gt;
        for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
        {&lt;br /&gt;
          sum[i] += voltage[i][j];&lt;br /&gt;
          if (voltage[i][j] &amp;gt; hotCellVolt)&lt;br /&gt;
            hotCellVolt = voltage[i][j];&lt;br /&gt;
          else if (voltage[i][j] &amp;lt; coldCellVolt)&lt;br /&gt;
            coldCellVolt = voltage[i][j];&lt;br /&gt;
          if(hotCellVolt &amp;gt;= ALARM)&lt;br /&gt;
          {&lt;br /&gt;
            buzzer=HIGH;&lt;br /&gt;
          }&lt;br /&gt;
          if(coldCellVolt &amp;lt;= LOWCELL)&lt;br /&gt;
          {&lt;br /&gt;
            dischargeProtect();&lt;br /&gt;
          }&lt;br /&gt;
          &lt;br /&gt;
        }  &lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
        &lt;br /&gt;
      //Execute alarm condition&lt;br /&gt;
      currentMillis = millis();&lt;br /&gt;
      if(buzzer)&lt;br /&gt;
      {&lt;br /&gt;
        digitalWrite(49,1);&lt;br /&gt;
        windDown(); // This loop should only be executed once and then skipped for at least 1 minute&lt;br /&gt;
        windDown_etime = currentMillis;&lt;br /&gt;
        Serial.println(&amp;quot;Buzzer Loop&amp;quot;);&lt;br /&gt;
      } else digitalWrite(49,0);        &lt;br /&gt;
      if (windDownFlag &amp;amp;&amp;amp; ((unsigned long)(currentMillis - windDown_etime) &amp;gt;= windDown_period))&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;post windDown windUp triggered&amp;quot;);&lt;br /&gt;
          windUp();&lt;br /&gt;
          windUp_etime = currentMillis;&lt;br /&gt;
        }&lt;br /&gt;
      if ((PANEL_VOLTS_READ &amp;gt;= dayLightVolt) &amp;amp;&amp;amp; (PANEL_AMPS_READ &amp;lt;= 1) &amp;amp;&amp;amp; (hotCellVolt &amp;lt;= windUpThreshold) &amp;amp;&amp;amp; ((unsigned long)(currentMillis - windUp_etime) &amp;gt;= windUp_period)) //Keep tweaking the controller to max&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;conditional windUp triggered&amp;quot;);&lt;br /&gt;
          windUp();&lt;br /&gt;
          windUp_etime = currentMillis;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
      if(unknownId != 0)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
        Serial.print(unknownId, HEX);&lt;br /&gt;
        Serial.println();&lt;br /&gt;
      }&lt;br /&gt;
     }&lt;br /&gt;
     else skip=LOW;    &lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      UpdateScreen(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode==0)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blues&lt;br /&gt;
    mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
    mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blacks&lt;br /&gt;
    mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,42 , 150, 191);   //Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,42 , 310, 191);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,234 , 150, 386);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170, 234 , 310, 386);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Lines&lt;br /&gt;
    mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
    mylcd.Draw_Line(11, 62, 149, 62);//Pack 1&lt;br /&gt;
    mylcd.Draw_Line(171, 62, 309, 62);//Pack 2&lt;br /&gt;
    mylcd.Draw_Line(11, 254, 149, 254);//Pack 3&lt;br /&gt;
    mylcd.Draw_Line(171, 254, 309, 254);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Reds &lt;br /&gt;
    mylcd.Set_Draw_color(RED);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,193 , 150, 214);//Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,193, 310, 214);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,384 , 150, 407);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170,384, 310, 407);//Pack 4&lt;br /&gt;
    //Title&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Set_Text_Mode(1);&lt;br /&gt;
    mylcd.Set_Text_Size(3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
    //Outline the screen&lt;br /&gt;
    mylcd.Set_Text_Size(2);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x04    (-)   x20    (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*10);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x06    (-)   x22    (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*22);&lt;br /&gt;
&lt;br /&gt;
    //credits, statusbar&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(int battery)&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(temperature[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
  &lt;br /&gt;
  if(c==7)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Set_Text_Mode(0);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
    mylcd.Print_Number_Float(sum[p], 3, xc+60, yc+22, '.', 0, ' ');&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  }&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw) // Convert the readings from the ADC to human readable&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit this loop will calculate it live but the look up table saves clock cycles&lt;br /&gt;
  //Supports Rounding&lt;br /&gt;
  //if( (raw*1.555)-26.0 - (int) ((raw*1.555)-26.0) &amp;gt;= 0.5)&lt;br /&gt;
  //  return (int)((raw*1.555)-25.0);&lt;br /&gt;
  //else&lt;br /&gt;
  //  return (int)((raw*1.555)-26.0);&lt;br /&gt;
  short static const table[256] = &lt;br /&gt;
                     {-26, -24,-23,-21,-20,-18,-17,-15,-14,-12,-10,-9,-7,-6,-4,-3,-1,&lt;br /&gt;
                      0,2,4,5,7,8,10,11,13,14,16,18,19,21,22,24,25,27,28,30,32,33,35,&lt;br /&gt;
                      36,38,39,41,42,44,46,47,49,50,52,53,55,56,58,60,61,63,64,66,67,&lt;br /&gt;
                      69,70,72,74,75,77,78,80,81,83,84,86,88,89,91,92,94,95,97,98,100,&lt;br /&gt;
                      102,103,105,106,108,109,111,112,114,116,117,119,120,122,123,125,&lt;br /&gt;
                      126,128,130,131,133,134,136,137,139,140,142,143,145,147,148,150,&lt;br /&gt;
                      151,153,154,156,157,159,161,162,164,165,167,168,170,171,173,175,&lt;br /&gt;
                      176,178,179,181,182,184,185,187,189,190,192,193,195,196,198,199,&lt;br /&gt;
                      201,203,204,206,207,209,210,212,213,215,217,218,220,221,223,224,&lt;br /&gt;
                      226,227,229,231,232,234,235,237,238,240,241,243,245,246,248,249,&lt;br /&gt;
                      251,252,254,255,257,259,260,262,263,265,266,268,269,271,273,274,&lt;br /&gt;
                      276,277,279,280,282,283,285,287,288,290,291,293,294,296,297,299,&lt;br /&gt;
                      301,302,304,305,307,308,310,311,313,315,316,318,319,321,322,324,&lt;br /&gt;
                      325,327,329,330,332,333,335,336,338,339,341,343,344,346,347,349,&lt;br /&gt;
                      350,352,353,355,357,358,360,361,363,364,366,367,369,371};&lt;br /&gt;
  return (int)table[raw]; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preTransmission() //Put RS485 into transmit mode by bringing the transmit and receive pins high&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 1);&lt;br /&gt;
  digitalWrite(MAX485_DE, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void postTransmission() //Put the RS485 into receive mode by bringing the transmit and receive pins low&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
}&lt;br /&gt;
void getControllerParams() // Hit the controller with a request for information&lt;br /&gt;
{&lt;br /&gt;
uint8_t result;&lt;br /&gt;
&lt;br /&gt;
  // Read input registers from the controller starting at address 0x3100)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readInputRegisters(0x3100, 5);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    PANEL_VOLTS_READ = node.getResponseBuffer(PANEL_VOLTS); //Data slot 0&lt;br /&gt;
    PANEL_AMPS_READ = node.getResponseBuffer(PANEL_AMPS); //Data slot 1&lt;br /&gt;
    BATT_VOLTS_READ = node.getResponseBuffer(BATT_VOLTS); //Data slot 4 (2,3 skipped, not needed)&lt;br /&gt;
    Serial.print(&amp;quot;Panel volts: &amp;quot;);&lt;br /&gt;
    Serial.println((float)PANEL_VOLTS_READ/100.00);&lt;br /&gt;
    Serial.print(&amp;quot;Panel Amps: &amp;quot;);&lt;br /&gt;
    Serial.println((float)PANEL_AMPS_READ/100.00);&lt;br /&gt;
    Serial.print(&amp;quot;Battery volts: &amp;quot;);&lt;br /&gt;
    Serial.println((float)BATT_VOLTS_READ/100.00);&lt;br /&gt;
    Serial.println();&lt;br /&gt;
  } &lt;br /&gt;
  else { //If there's an error send it to the console&lt;br /&gt;
    Serial.print(&amp;quot;Reading controller parameters failed, error:&amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
  //delay(1000);&lt;br /&gt;
&lt;br /&gt;
  // Read charging parameters from the controller starting at address 0x9000)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readHoldingRegisters(0x9000, 15);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    //Some values are not collected because we will always use the defaults&lt;br /&gt;
    OVERVOLT_DISC_READ = node.getResponseBuffer(OVERVOLT_DISC);&lt;br /&gt;
    CHARGING_LIMIT_READ = node.getResponseBuffer(CHARGING_LIMIT);&lt;br /&gt;
    OVERVOLT_RECON_READ = node.getResponseBuffer(OVERVOLT_RECON);&lt;br /&gt;
    EQUILIBRIUM_CV_READ = node.getResponseBuffer(EQUILIBRIUM_CV);&lt;br /&gt;
    BOOST_CV_READ = node.getResponseBuffer(BOOST_CV);&lt;br /&gt;
    FLOAT_CV_READ = node.getResponseBuffer(FLOAT_CV);&lt;br /&gt;
    BOOST_RECON_READ = node.getResponseBuffer(BOOST_RECON);&lt;br /&gt;
    LOW_VOLT_RECON_READ = node.getResponseBuffer(LOW_VOLT);&lt;br /&gt;
    UNDERVOLT_RECOVERY_READ = node.getResponseBuffer(UNDERVOLT_RECOV);&lt;br /&gt;
    UNDERVOLT_WARNING_READ = node.getResponseBuffer(UNDERVOLT_WARN);&lt;br /&gt;
    LOW_VOLT_DISC_READ = node.getResponseBuffer(LOW_VOLT_DISC);&lt;br /&gt;
    DISCHARGE_LIMIT_READ = node.getResponseBuffer(DISCHARGE_LIMIT);&lt;br /&gt;
  } &lt;br /&gt;
  else {&lt;br /&gt;
    Serial.print(&amp;quot;The charging parameters failed to read, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //delay(2000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void windDown() // Bring the controller charge voltage down so the hot cell will kalm&lt;br /&gt;
{&lt;br /&gt;
  OVERVOLT_DISC_SETTO = BATT_VOLTS_READ + 50;&lt;br /&gt;
  CHARGING_LIMIT_SETTO = BATT_VOLTS_READ - 20;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  BOOST_CV_SETTO = BATT_VOLTS_READ - 40;&lt;br /&gt;
  FLOAT_CV_SETTO = BATT_VOLTS_READ - 50;&lt;br /&gt;
  BOOST_RECON_SETTO = BATT_VOLTS_READ - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
  windDownFlag = HIGH;&lt;br /&gt;
  Serial.println(&amp;quot;Wind down has been prepared for sending&amp;quot;);&lt;br /&gt;
  //Insert a timer to wind up in 2 minutes&lt;br /&gt;
}&lt;br /&gt;
void windUp() // Bring the controller charge voltage as close to max as possible&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  unsigned short difference = int((ALARM - hotCellVolt) * 100);&lt;br /&gt;
  unsigned short setvolt = BATT_VOLTS_READ + difference;&lt;br /&gt;
  if (difference &amp;gt; 10)&lt;br /&gt;
  {&lt;br /&gt;
    OVERVOLT_DISC_SETTO = (setvolt + 50);&lt;br /&gt;
    CHARGING_LIMIT_SETTO = setvolt;&lt;br /&gt;
    OVERVOLT_RECON_SETTO = setvolt - 10;&lt;br /&gt;
    EQUILIBRIUM_CV_SETTO = setvolt - 20;&lt;br /&gt;
    BOOST_CV_SETTO = setvolt - 30;&lt;br /&gt;
    FLOAT_CV_SETTO = setvolt - 40;&lt;br /&gt;
    BOOST_RECON_SETTO = setvolt - 100;&lt;br /&gt;
    Serial.println(&amp;quot;Wind Up has been prepared for sending&amp;quot;);&lt;br /&gt;
    updateController();&lt;br /&gt;
    windDownFlag = LOW;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
void dischargeProtect()&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  currentMillis = millis();&lt;br /&gt;
  if (((DISCHARGE_LIMIT_READ + 50) &amp;lt; BATT_VOLTS_READ) &amp;amp;&amp;amp; (unsigned long)(currentMillis - dischargeProtect_etime) &amp;gt;= dischargeProtect_period)&lt;br /&gt;
  {&lt;br /&gt;
    UNDERVOLT_RECOVERY_SETTO = BATT_VOLTS_READ + 50;&lt;br /&gt;
    UNDERVOLT_WARNING_SETTO = BATT_VOLTS_READ + 30;&lt;br /&gt;
    LOW_VOLT_RECON_SETTO = BATT_VOLTS_READ + 20;&lt;br /&gt;
    LOW_VOLT_DISC_SETTO = BATT_VOLTS_READ - 20;&lt;br /&gt;
    DISCHARGE_LIMIT_SETTO = BATT_VOLTS_READ - 50;&lt;br /&gt;
    Serial.println(&amp;quot;Overdischarge protection adjustment prepared&amp;quot;);&lt;br /&gt;
    updateController();&lt;br /&gt;
    dischargeProtect_etime = currentMillis;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
void updateController() // Send new information to the controller. Something unusual discovered with the Epever AN controller is that it will not change 9003-9007 &lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  node.clearTransmitBuffer(); //Prepare the buffer with new data, clear and fill&lt;br /&gt;
  node.setTransmitBuffer(0, def_BATT_TYPE);&lt;br /&gt;
  node.setTransmitBuffer(1, def_BATT_AH);&lt;br /&gt;
  node.setTransmitBuffer(2, def_TEMP_COMP);&lt;br /&gt;
  node.setTransmitBuffer(3, OVERVOLT_DISC_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(4, CHARGING_LIMIT_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(5, OVERVOLT_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(6, EQUILIBRIUM_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(7, BOOST_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(8, FLOAT_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(9, BOOST_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(10, LOW_VOLT_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(11, UNDERVOLT_RECOVERY_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(12, UNDERVOLT_WARNING_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(13, LOW_VOLT_DISC_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(14, DISCHARGE_LIMIT_SETTO);&lt;br /&gt;
  &lt;br /&gt;
  int result = (node.writeMultipleRegisters(0x9000,15)); //Yeet this new info to the controller&lt;br /&gt;
  if (result == 0) //Verify&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameters 9000-900F changed sucessfully&amp;quot;); // For Diagnostic console&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameters 9000-900F change failed, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=99</id>
		<title>CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=99"/>
		<updated>2020-12-10T20:22:35Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */ Epever integration has not been tested yet&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
This was developed to test communication to the EPEVER AN Solar controller from the Arduino&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;mcp_can.h&amp;gt;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library http://www.lcdwiki.com/3.5inch_Arduino_Display-UNO&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
#include &amp;lt;ModbusMaster.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS                4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS                8     //Hazardous to modify&lt;br /&gt;
#define REFRESH                 1000   //Refresh rate display&lt;br /&gt;
#define ALARM                   3.640    //Alarm threshold&lt;br /&gt;
#define LOWCELL                 3.100&lt;br /&gt;
#define windDown_period         600000 //Delay before controller attempts to increase the charge voltage, giving cells time to settle&lt;br /&gt;
#define windUp_period           60000&lt;br /&gt;
#define windUpThreshold         3.550 //WindUp function will not call again until a cell reaches this voltage&lt;br /&gt;
#define dischargeProtect_period 600000&lt;br /&gt;
&lt;br /&gt;
//Define the default values for your pack here, value *100, no decimal&lt;br /&gt;
#define def_BATT_TYPE           0000&lt;br /&gt;
#define def_BATT_AH             880&lt;br /&gt;
#define def_TEMP_COMP           300&lt;br /&gt;
#define def_OVERVOLT_DISC_VAL   2950&lt;br /&gt;
#define def_CHARGING_LIMIT_VAL  2860&lt;br /&gt;
#define def_OVERVOLT_RECON_VAL  2880&lt;br /&gt;
#define def_EQUILIBRIUM_CV_VAL  2830&lt;br /&gt;
#define def_BOOST_CV_VAL        2830&lt;br /&gt;
#define def_FLOAT_CV_VAL        2760        &lt;br /&gt;
#define def_BOOST_RECON_VAL     2640 &lt;br /&gt;
#define def_LOW_VOLT_RECON      2350&lt;br /&gt;
#define def_UNDERVOLT_RECOV     2440&lt;br /&gt;
#define def_UNDERVOLT_WARNING   2400&lt;br /&gt;
#define def_LOW_VOLT_DISC       2220&lt;br /&gt;
#define def_DISCHARGE_LIMIT     2120&lt;br /&gt;
#define dayLightVolt            3500  &lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x1863&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RS485 converter connections&lt;br /&gt;
#define MAX485_DE   49&lt;br /&gt;
#define MAX485_RE   48&lt;br /&gt;
&lt;br /&gt;
// For Epever AN controller MODBUS read&lt;br /&gt;
#define PANEL_VOLTS     0x00&lt;br /&gt;
#define PANEL_AMPS      0x01&lt;br /&gt;
#define PANEL_POWER_L   0x02&lt;br /&gt;
#define PANEL_POWER_H   0x03&lt;br /&gt;
#define BATT_VOLTS      0x04&lt;br /&gt;
#define BATT_AMPS       0x05&lt;br /&gt;
#define BATT_POWER_L    0x06&lt;br /&gt;
#define BATT_POWER_H    0x07&lt;br /&gt;
#define OVERVOLT_DISC   0x03&lt;br /&gt;
#define CHARGING_LIMIT  0x04&lt;br /&gt;
#define OVERVOLT_RECON  0x05&lt;br /&gt;
#define EQUILIBRIUM_CV  0x06&lt;br /&gt;
#define BOOST_CV        0x07&lt;br /&gt;
#define FLOAT_CV        0x08&lt;br /&gt;
#define BOOST_RECON     0x09&lt;br /&gt;
#define LOW_VOLT        0x0A&lt;br /&gt;
#define UNDERVOLT_RECOV 0x0B&lt;br /&gt;
#define UNDERVOLT_WARN  0x0C&lt;br /&gt;
#define LOW_VOLT_DISC   0x0D&lt;br /&gt;
#define DISCHARGE_LIMIT 0x0E&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = LOW;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
unsigned long currentMillis;&lt;br /&gt;
&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
int temperature[NUMPACKS][NUMCELLS];&lt;br /&gt;
&lt;br /&gt;
//Pack Parameters - you will fill this info in once you find the CAN address of your packs. Only the last two numbers will be relevant&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
float hotCellVolt = 0;&lt;br /&gt;
float coldCellVolt = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Variables for holding the solar controller's set values&lt;br /&gt;
unsigned short OVERVOLT_DISC_READ;&lt;br /&gt;
unsigned short CHARGING_LIMIT_READ;&lt;br /&gt;
unsigned short OVERVOLT_RECON_READ;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_READ;&lt;br /&gt;
unsigned short BOOST_CV_READ;&lt;br /&gt;
unsigned short FLOAT_CV_READ;&lt;br /&gt;
unsigned short BOOST_RECON_READ;&lt;br /&gt;
unsigned short LOW_VOLT_RECON_READ;&lt;br /&gt;
unsigned short UNDERVOLT_RECOVERY_READ;&lt;br /&gt;
unsigned short UNDERVOLT_WARNING_READ;&lt;br /&gt;
unsigned short LOW_VOLT_DISC_READ;&lt;br /&gt;
unsigned short DISCHARGE_LIMIT_READ;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding register values from the controller&lt;br /&gt;
unsigned short PANEL_VOLTS_READ;&lt;br /&gt;
unsigned short PANEL_AMPS_READ;&lt;br /&gt;
unsigned short BATT_VOLTS_READ;&lt;br /&gt;
unsigned short BATT_AMPS_READ;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding values to be sent to the solar controller&lt;br /&gt;
unsigned short OVERVOLT_DISC_SETTO;&lt;br /&gt;
unsigned short CHARGING_LIMIT_SETTO;&lt;br /&gt;
unsigned short OVERVOLT_RECON_SETTO;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_CV_SETTO;&lt;br /&gt;
unsigned short FLOAT_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_RECON_SETTO;&lt;br /&gt;
unsigned short LOW_VOLT_RECON_SETTO;&lt;br /&gt;
unsigned short UNDERVOLT_RECOVERY_SETTO;&lt;br /&gt;
unsigned short UNDERVOLT_WARNING_SETTO;&lt;br /&gt;
unsigned short LOW_VOLT_DISC_SETTO;&lt;br /&gt;
unsigned short DISCHARGE_LIMIT_SETTO;&lt;br /&gt;
&lt;br /&gt;
//Variables for working with the controller&lt;br /&gt;
bool windDownFlag = LOW;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
&lt;br /&gt;
//Low failure rate timer&lt;br /&gt;
//const int windDown_period = 60000;&lt;br /&gt;
unsigned long windDown_etime = 0;&lt;br /&gt;
//const long windUp_period = 600000;&lt;br /&gt;
unsigned long windUp_etime = 0;&lt;br /&gt;
unsigned long dischargeProtect_etime = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(53);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
// instantiate ModbusMaster object&lt;br /&gt;
ModbusMaster node;&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
long st, fn;&lt;br /&gt;
int q;  &lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.print(&amp;quot;My LCD ID: &amp;quot;);&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temperature[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  pinMode(MAX485_RE, OUTPUT);&lt;br /&gt;
  pinMode(MAX485_DE, OUTPUT);&lt;br /&gt;
  // Init in receive mode&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
  &lt;br /&gt;
  // Modbus setup at 115200 baud&lt;br /&gt;
  Serial1.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  // EPEver Device ID 1&lt;br /&gt;
  node.begin(1, Serial1);&lt;br /&gt;
&lt;br /&gt;
  // Callbacks&lt;br /&gt;
  node.preTransmission(preTransmission);&lt;br /&gt;
  node.postTransmission(postTransmission);&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);        &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    //Serial.print(&amp;quot;p&amp;quot;);//packet received&lt;br /&gt;
&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temperature[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temperature[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temperature[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temperature[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temperature code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temperature code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        //for(int i = 0; i&amp;lt;len; i++) {buf3[i] = buf[i];}&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500) ;//{for(int i = 0; i&amp;lt;len; i++){buf5[i] = buf[i];}}&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00) ;//{for(int i = 0; i&amp;lt;len; i++){bufA[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000) ;//{for(int i = 0; i&amp;lt;len; i++){buf0[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][7] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][6] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][5] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf20[i] = buf[i];} &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][4] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][3] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][2] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf21[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][1] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][0] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf22[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      hotCellVolt = voltage[0][0];&lt;br /&gt;
      coldCellVolt = voltage[0][0];&lt;br /&gt;
      for(int i=0; i&amp;lt;NUMPACKS;i++) //Calculate a pack sum and check for hot cells&lt;br /&gt;
      {&lt;br /&gt;
        sum[i]=0.0;&lt;br /&gt;
        for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
        {&lt;br /&gt;
          sum[i] += voltage[i][j];&lt;br /&gt;
          if (voltage[i][j] &amp;gt; hotCellVolt)&lt;br /&gt;
            hotCellVolt = voltage[i][j];&lt;br /&gt;
          else if (voltage[i][j] &amp;lt; coldCellVolt)&lt;br /&gt;
            coldCellVolt = voltage[i][j];&lt;br /&gt;
          if(hotCellVolt &amp;gt;= ALARM)&lt;br /&gt;
          {&lt;br /&gt;
            buzzer=HIGH;&lt;br /&gt;
          }&lt;br /&gt;
          if(coldCellVolt &amp;lt;= LOWCELL)&lt;br /&gt;
          {&lt;br /&gt;
            dischargeProtect();&lt;br /&gt;
          }&lt;br /&gt;
          &lt;br /&gt;
        }  &lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
        &lt;br /&gt;
      //Execute alarm condition&lt;br /&gt;
      currentMillis = millis();&lt;br /&gt;
      if(buzzer)&lt;br /&gt;
      {&lt;br /&gt;
        digitalWrite(49,1);&lt;br /&gt;
        windDown(); // This loop should only be executed once and then skipped for at least 1 minute&lt;br /&gt;
        windDown_etime = currentMillis;&lt;br /&gt;
        Serial.println(&amp;quot;Buzzer Loop&amp;quot;);&lt;br /&gt;
      } else digitalWrite(49,0);        &lt;br /&gt;
      if (windDownFlag &amp;amp;&amp;amp; ((unsigned long)(currentMillis - windDown_etime) &amp;gt;= windDown_period))&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;post windDown windUp triggered&amp;quot;);&lt;br /&gt;
          windUp();&lt;br /&gt;
          windUp_etime = currentMillis;&lt;br /&gt;
        }&lt;br /&gt;
      if ((PANEL_VOLTS_READ &amp;gt;= dayLightVolt) &amp;amp;&amp;amp; (PANEL_AMPS_READ &amp;lt;= 1) &amp;amp;&amp;amp; (hotCellVolt &amp;lt;= windUpThreshold) &amp;amp;&amp;amp; ((unsigned long)(currentMillis - windUp_etime) &amp;gt;= windUp_period)) //Keep tweaking the controller to max&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;conditional windUp triggered&amp;quot;);&lt;br /&gt;
          windUp();&lt;br /&gt;
          windUp_etime = currentMillis;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
      if(unknownId != 0)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
        Serial.print(unknownId, HEX);&lt;br /&gt;
        Serial.println();&lt;br /&gt;
      }&lt;br /&gt;
     }&lt;br /&gt;
     else skip=LOW;    &lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      UpdateScreen(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode==0)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blues&lt;br /&gt;
    mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
    mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blacks&lt;br /&gt;
    mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,42 , 150, 191);   //Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,42 , 310, 191);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,234 , 150, 386);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170, 234 , 310, 386);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Lines&lt;br /&gt;
    mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
    mylcd.Draw_Line(11, 62, 149, 62);//Pack 1&lt;br /&gt;
    mylcd.Draw_Line(171, 62, 309, 62);//Pack 2&lt;br /&gt;
    mylcd.Draw_Line(11, 254, 149, 254);//Pack 3&lt;br /&gt;
    mylcd.Draw_Line(171, 254, 309, 254);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Reds &lt;br /&gt;
    mylcd.Set_Draw_color(RED);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,193 , 150, 214);//Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,193, 310, 214);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,384 , 150, 407);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170,384, 310, 407);//Pack 4&lt;br /&gt;
    //Title&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Set_Text_Mode(1);&lt;br /&gt;
    mylcd.Set_Text_Size(3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
    //Outline the screen&lt;br /&gt;
    mylcd.Set_Text_Size(2);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x04    (-)   x20    (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*10);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x06    (-)   x22    (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*22);&lt;br /&gt;
&lt;br /&gt;
    //credits, statusbar&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(int battery)&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(temperature[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
  &lt;br /&gt;
  if(c==7)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Set_Text_Mode(0);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
    mylcd.Print_Number_Float(sum[p], 3, xc+60, yc+22, '.', 0, ' ');&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  }&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw) // Convert the readings from the ADC to human readable&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit this loop will calculate it live but the look up table saves clock cycles&lt;br /&gt;
  //Supports Rounding&lt;br /&gt;
  //if( (raw*1.555)-26.0 - (int) ((raw*1.555)-26.0) &amp;gt;= 0.5)&lt;br /&gt;
  //  return (int)((raw*1.555)-25.0);&lt;br /&gt;
  //else&lt;br /&gt;
  //  return (int)((raw*1.555)-26.0);&lt;br /&gt;
  short static const table[256] = &lt;br /&gt;
                     {-26, -24,-23,-21,-20,-18,-17,-15,-14,-12,-10,-9,-7,-6,-4,-3,-1,&lt;br /&gt;
                      0,2,4,5,7,8,10,11,13,14,16,18,19,21,22,24,25,27,28,30,32,33,35,&lt;br /&gt;
                      36,38,39,41,42,44,46,47,49,50,52,53,55,56,58,60,61,63,64,66,67,&lt;br /&gt;
                      69,70,72,74,75,77,78,80,81,83,84,86,88,89,91,92,94,95,97,98,100,&lt;br /&gt;
                      102,103,105,106,108,109,111,112,114,116,117,119,120,122,123,125,&lt;br /&gt;
                      126,128,130,131,133,134,136,137,139,140,142,143,145,147,148,150,&lt;br /&gt;
                      151,153,154,156,157,159,161,162,164,165,167,168,170,171,173,175,&lt;br /&gt;
                      176,178,179,181,182,184,185,187,189,190,192,193,195,196,198,199,&lt;br /&gt;
                      201,203,204,206,207,209,210,212,213,215,217,218,220,221,223,224,&lt;br /&gt;
                      226,227,229,231,232,234,235,237,238,240,241,243,245,246,248,249,&lt;br /&gt;
                      251,252,254,255,257,259,260,262,263,265,266,268,269,271,273,274,&lt;br /&gt;
                      276,277,279,280,282,283,285,287,288,290,291,293,294,296,297,299,&lt;br /&gt;
                      301,302,304,305,307,308,310,311,313,315,316,318,319,321,322,324,&lt;br /&gt;
                      325,327,329,330,332,333,335,336,338,339,341,343,344,346,347,349,&lt;br /&gt;
                      350,352,353,355,357,358,360,361,363,364,366,367,369,371};&lt;br /&gt;
  return (int)table[raw]; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preTransmission() //Put RS485 into transmit mode by bringing the transmit and receive pins high&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 1);&lt;br /&gt;
  digitalWrite(MAX485_DE, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void postTransmission() //Put the RS485 into receive mode by bringing the transmit and receive pins low&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
}&lt;br /&gt;
void getControllerParams() // Hit the controller with a request for information&lt;br /&gt;
{&lt;br /&gt;
uint8_t result;&lt;br /&gt;
&lt;br /&gt;
  // Read input registers from the controller starting at address 0x3100)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readInputRegisters(0x3100, 5);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    PANEL_VOLTS_READ = node.getResponseBuffer(PANEL_VOLTS); //Data slot 0&lt;br /&gt;
    PANEL_AMPS_READ = node.getResponseBuffer(PANEL_AMPS); //Data slot 1&lt;br /&gt;
    BATT_VOLTS_READ = node.getResponseBuffer(BATT_VOLTS); //Data slot 4 (2,3 skipped, not needed)&lt;br /&gt;
    Serial.print(&amp;quot;Panel volts: &amp;quot;);&lt;br /&gt;
    Serial.println((float)PANEL_VOLTS_READ/100.00);&lt;br /&gt;
    Serial.print(&amp;quot;Panel Amps: &amp;quot;);&lt;br /&gt;
    Serial.println((float)PANEL_AMPS_READ/100.00);&lt;br /&gt;
    Serial.print(&amp;quot;Battery volts: &amp;quot;);&lt;br /&gt;
    Serial.println((float)BATT_VOLTS_READ/100.00);&lt;br /&gt;
    Serial.println();&lt;br /&gt;
  } &lt;br /&gt;
  else { //If there's an error send it to the console&lt;br /&gt;
    Serial.print(&amp;quot;Reading controller parameters failed, error:&amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
  //delay(1000);&lt;br /&gt;
&lt;br /&gt;
  // Read charging parameters from the controller starting at address 0x9000)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readHoldingRegisters(0x9000, 15);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    //Some values are not collected because we will always use the defaults&lt;br /&gt;
    OVERVOLT_DISC_READ = node.getResponseBuffer(OVERVOLT_DISC);&lt;br /&gt;
    CHARGING_LIMIT_READ = node.getResponseBuffer(CHARGING_LIMIT);&lt;br /&gt;
    OVERVOLT_RECON_READ = node.getResponseBuffer(OVERVOLT_RECON);&lt;br /&gt;
    EQUILIBRIUM_CV_READ = node.getResponseBuffer(EQUILIBRIUM_CV);&lt;br /&gt;
    BOOST_CV_READ = node.getResponseBuffer(BOOST_CV);&lt;br /&gt;
    FLOAT_CV_READ = node.getResponseBuffer(FLOAT_CV);&lt;br /&gt;
    BOOST_RECON_READ = node.getResponseBuffer(BOOST_RECON);&lt;br /&gt;
    LOW_VOLT_RECON_READ = node.getResponseBuffer(LOW_VOLT);&lt;br /&gt;
    UNDERVOLT_RECOVERY_READ = node.getResponseBuffer(UNDERVOLT_RECOV);&lt;br /&gt;
    UNDERVOLT_WARNING_READ = node.getResponseBuffer(UNDERVOLT_WARN);&lt;br /&gt;
    LOW_VOLT_DISC_READ = node.getResponseBuffer(LOW_VOLT_DISC);&lt;br /&gt;
    DISCHARGE_LIMIT_READ = node.getResponseBuffer(DISCHARGE_LIMIT);&lt;br /&gt;
  } &lt;br /&gt;
  else {&lt;br /&gt;
    Serial.print(&amp;quot;The charging parameters failed to read, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //delay(2000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void windDown() // Bring the controller charge voltage down so the hot cell will kalm&lt;br /&gt;
{&lt;br /&gt;
  OVERVOLT_DISC_SETTO = BATT_VOLTS_READ + 50;&lt;br /&gt;
  CHARGING_LIMIT_SETTO = BATT_VOLTS_READ - 20;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  BOOST_CV_SETTO = BATT_VOLTS_READ - 40;&lt;br /&gt;
  FLOAT_CV_SETTO = BATT_VOLTS_READ - 50;&lt;br /&gt;
  BOOST_RECON_SETTO = BATT_VOLTS_READ - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
  windDownFlag = HIGH;&lt;br /&gt;
  Serial.println(&amp;quot;Wind down has been prepared for sending&amp;quot;);&lt;br /&gt;
  //Insert a timer to wind up in 2 minutes&lt;br /&gt;
}&lt;br /&gt;
void windUp() // Bring the controller charge voltage as close to max as possible&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  unsigned short difference = int((ALARM - hotCellVolt) * 100);&lt;br /&gt;
  unsigned short setvolt = BATT_VOLTS_READ + difference;&lt;br /&gt;
  if (difference &amp;gt; 10)&lt;br /&gt;
  {&lt;br /&gt;
    OVERVOLT_DISC_SETTO = (setvolt + 50);&lt;br /&gt;
    CHARGING_LIMIT_SETTO = setvolt;&lt;br /&gt;
    OVERVOLT_RECON_SETTO = setvolt - 10;&lt;br /&gt;
    EQUILIBRIUM_CV_SETTO = setvolt - 20;&lt;br /&gt;
    BOOST_CV_SETTO = setvolt - 30;&lt;br /&gt;
    FLOAT_CV_SETTO = setvolt - 40;&lt;br /&gt;
    BOOST_RECON_SETTO = setvolt - 100;&lt;br /&gt;
    Serial.println(&amp;quot;Wind Up has been prepared for sending&amp;quot;);&lt;br /&gt;
    updateController();&lt;br /&gt;
    windDownFlag = LOW;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
void dischargeProtect()&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  currentMillis = millis();&lt;br /&gt;
  if (((DISCHARGE_LIMIT_SETTO + 50) &amp;gt; BATT_VOLTS_READ) &amp;amp;&amp;amp; (unsigned long)(currentMillis - dischargeProtect_etime) &amp;gt;= dischargeProtect_period)&lt;br /&gt;
  {&lt;br /&gt;
    UNDERVOLT_RECOVERY_SETTO = BATT_VOLTS_READ + 50;&lt;br /&gt;
    UNDERVOLT_WARNING_SETTO = BATT_VOLTS_READ + 30;&lt;br /&gt;
    LOW_VOLT_RECON_SETTO = BATT_VOLTS_READ + 20;&lt;br /&gt;
    LOW_VOLT_DISC_SETTO = BATT_VOLTS_READ - 20;&lt;br /&gt;
    DISCHARGE_LIMIT_SETTO = BATT_VOLTS_READ - 50;&lt;br /&gt;
    Serial.println(&amp;quot;Overdischarge protection adjustment prepared&amp;quot;);&lt;br /&gt;
    updateController();&lt;br /&gt;
    dischargeProtect_etime = currentMillis;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
void updateController() // Send new information to the controller. Something unusual discovered with the Epever AN controller is that it will not change 9003-9007 &lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  node.clearTransmitBuffer(); //Prepare the buffer with new data, clear and fill&lt;br /&gt;
  node.setTransmitBuffer(0, def_BATT_TYPE);&lt;br /&gt;
  node.setTransmitBuffer(1, def_BATT_AH);&lt;br /&gt;
  node.setTransmitBuffer(2, def_TEMP_COMP);&lt;br /&gt;
  node.setTransmitBuffer(3, OVERVOLT_DISC_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(4, CHARGING_LIMIT_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(5, OVERVOLT_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(6, EQUILIBRIUM_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(7, BOOST_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(8, FLOAT_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(9, BOOST_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(10, LOW_VOLT_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(11, UNDERVOLT_RECOVERY_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(12, UNDERVOLT_WARNING_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(13, LOW_VOLT_DISC_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(14, DISCHARGE_LIMIT_SETTO);&lt;br /&gt;
  &lt;br /&gt;
  int result = (node.writeMultipleRegisters(0x9000,15)); //Yeet this new info to the controller&lt;br /&gt;
  if (result == 0) //Verify&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameters 9000-900F changed sucessfully&amp;quot;); // For Diagnostic console&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameters 9000-900F change failed, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=98</id>
		<title>CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=98"/>
		<updated>2020-12-10T04:40:19Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */ Values can be read from controller but not yet written properly&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
This was developed to test communication to the EPEVER AN Solar controller from the Arduino&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;mcp_can.h&amp;gt;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library http://www.lcdwiki.com/3.5inch_Arduino_Display-UNO&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
#include &amp;lt;ModbusMaster.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS                4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS                8     //Hazardous to modify&lt;br /&gt;
#define REFRESH                 1000   //Refresh rate display&lt;br /&gt;
#define ALARM                   3.640    //Alarm threshold&lt;br /&gt;
#define windUpDelay             300000 //Delay before controller attempts to increase the charge voltage, giving cells time to settle&lt;br /&gt;
#define windUpThreshold         3.550 //WindUp function will not call again until a cell reaches this voltage&lt;br /&gt;
&lt;br /&gt;
//Define the default values for your pack here, value *100, no decimal&lt;br /&gt;
#define def_BATT_TYPE           0000&lt;br /&gt;
#define def_BATT_AH             880&lt;br /&gt;
#define def_TEMP_COMP           300&lt;br /&gt;
#define def_OVERVOLT_DISC_VAL   2950&lt;br /&gt;
#define def_CHARGING_LIMIT_VAL  2860&lt;br /&gt;
#define def_OVERVOLT_RECON_VAL  2880&lt;br /&gt;
#define def_EQUILIBRIUM_CV_VAL  2830&lt;br /&gt;
#define def_BOOST_CV_VAL        2830&lt;br /&gt;
#define def_FLOAT_CV_VAL        2760        &lt;br /&gt;
#define def_BOOST_RECON_VAL     2640 &lt;br /&gt;
#define def_LOW_VOLT_RECON      2350&lt;br /&gt;
#define def_UNDERVOLT_RECOV     2440&lt;br /&gt;
#define def_UNDERVOLT_WARNING   2400&lt;br /&gt;
#define def_LOW_VOLT_DISC       2220&lt;br /&gt;
#define def_DISCHARGE_LIMIT     2120&lt;br /&gt;
#define dayLightVolt            3500  &lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x1863&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RS485 converter connections&lt;br /&gt;
#define MAX485_DE   49&lt;br /&gt;
#define MAX485_RE   48&lt;br /&gt;
&lt;br /&gt;
// For Epever AN controller MODBUS read&lt;br /&gt;
#define PANEL_VOLTS     0x00&lt;br /&gt;
#define PANEL_AMPS      0x01&lt;br /&gt;
#define PANEL_POWER_L   0x02&lt;br /&gt;
#define PANEL_POWER_H   0x03&lt;br /&gt;
#define BATT_VOLTS      0x04&lt;br /&gt;
#define BATT_AMPS       0x05&lt;br /&gt;
#define BATT_POWER_L    0x06&lt;br /&gt;
#define BATT_POWER_H    0x07&lt;br /&gt;
#define OVERVOLT_DISC   0x03&lt;br /&gt;
#define CHARGING_LIMIT  0x04&lt;br /&gt;
#define OVERVOLT_RECON  0x05&lt;br /&gt;
#define EQUILIBRIUM_CV  0x06&lt;br /&gt;
#define BOOST_CV        0x07&lt;br /&gt;
#define FLOAT_CV        0x08&lt;br /&gt;
#define BOOST_RECON     0x09&lt;br /&gt;
#define LOW_VOLT        0x0A&lt;br /&gt;
#define UNDERVOLT_RECOV 0x0B&lt;br /&gt;
#define UNDERVOLT_WARN  0x0C&lt;br /&gt;
#define LOW_VOLT_DISC   0x0D&lt;br /&gt;
#define DISCHARGE_LIMIT 0x0E&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = LOW;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
unsigned long currentMillis;&lt;br /&gt;
&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
int temperature[NUMPACKS][NUMCELLS];&lt;br /&gt;
&lt;br /&gt;
//Pack Parameters - you will fill this info in once you find the CAN address of your packs. Only the last two numbers will be relevant&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
float hotCellVolt = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Variables for holding the solar controller's set values&lt;br /&gt;
unsigned short OVERVOLT_DISC_READ;&lt;br /&gt;
unsigned short CHARGING_LIMIT_READ;&lt;br /&gt;
unsigned short OVERVOLT_RECON_READ;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_READ;&lt;br /&gt;
unsigned short BOOST_CV_READ;&lt;br /&gt;
unsigned short FLOAT_CV_READ;&lt;br /&gt;
unsigned short BOOST_RECON_READ;&lt;br /&gt;
unsigned short LOW_VOLT_RECON_READ;&lt;br /&gt;
unsigned short UNDERVOLT_RECOVERY_READ;&lt;br /&gt;
unsigned short UNDERVOLT_WARNING_READ;&lt;br /&gt;
unsigned short LOW_VOLT_DISC_READ;&lt;br /&gt;
unsigned short DISCHARGE_LIMIT_READ;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding register values from the controller&lt;br /&gt;
unsigned short PANEL_VOLTS_READ;&lt;br /&gt;
unsigned short PANEL_AMPS_READ;&lt;br /&gt;
unsigned short BATT_VOLTS_READ;&lt;br /&gt;
unsigned short BATT_AMPS_READ;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding values to be sent to the solar controller&lt;br /&gt;
unsigned short OVERVOLT_DISC_SETTO;&lt;br /&gt;
unsigned short CHARGING_LIMIT_SETTO;&lt;br /&gt;
unsigned short OVERVOLT_RECON_SETTO;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_CV_SETTO;&lt;br /&gt;
unsigned short FLOAT_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_RECON_SETTO;&lt;br /&gt;
unsigned short LOW_VOLT_RECON_SETTO;&lt;br /&gt;
unsigned short UNDERVOLT_RECOVERY_SETTO;&lt;br /&gt;
unsigned short UNDERVOLT_WARNING_SETTO;&lt;br /&gt;
unsigned short LOW_VOLT_DISC_SETTO;&lt;br /&gt;
unsigned short DISCHARGE_LIMIT_SETTO;&lt;br /&gt;
&lt;br /&gt;
//Variables for working with the controller&lt;br /&gt;
bool windDownFlag = LOW;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
&lt;br /&gt;
//Low failure rate timer&lt;br /&gt;
const int windDown_period = 60000;&lt;br /&gt;
unsigned long windDown_etime = 0;&lt;br /&gt;
const long windUp_period = 600000;&lt;br /&gt;
unsigned long windUp_etime = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
// instantiate ModbusMaster object&lt;br /&gt;
ModbusMaster node;&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
long st, fn;&lt;br /&gt;
int q;  &lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.print(&amp;quot;My LCD ID: &amp;quot;);&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temperature[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  pinMode(MAX485_RE, OUTPUT);&lt;br /&gt;
  pinMode(MAX485_DE, OUTPUT);&lt;br /&gt;
  // Init in receive mode&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
  &lt;br /&gt;
  // Modbus setup at 115200 baud&lt;br /&gt;
  Serial1.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  // EPEver Device ID 1&lt;br /&gt;
  node.begin(1, Serial1);&lt;br /&gt;
&lt;br /&gt;
  // Callbacks&lt;br /&gt;
  node.preTransmission(preTransmission);&lt;br /&gt;
  node.postTransmission(postTransmission);&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);        &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    //Serial.print(&amp;quot;p&amp;quot;);//packet received&lt;br /&gt;
&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temperature[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temperature[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temperature[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temperature[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temperature code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temperature code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        //for(int i = 0; i&amp;lt;len; i++) {buf3[i] = buf[i];}&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500) ;//{for(int i = 0; i&amp;lt;len; i++){buf5[i] = buf[i];}}&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00) ;//{for(int i = 0; i&amp;lt;len; i++){bufA[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000) ;//{for(int i = 0; i&amp;lt;len; i++){buf0[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][7] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][6] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][5] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf20[i] = buf[i];} &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][4] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][3] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][2] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf21[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][1] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][0] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf22[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      hotCellVolt = 0;&lt;br /&gt;
      for(int i=0; i&amp;lt;NUMPACKS;i++) //Calculate a pack sum and check for hot cells&lt;br /&gt;
      {&lt;br /&gt;
        sum[i]=0.0;&lt;br /&gt;
        for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
        {&lt;br /&gt;
          sum[i] += voltage[i][j];&lt;br /&gt;
          if (voltage[i][j] &amp;gt; hotCellVolt)&lt;br /&gt;
            hotCellVolt = voltage[i][j];&lt;br /&gt;
          if(hotCellVolt &amp;gt;= ALARM)&lt;br /&gt;
          {&lt;br /&gt;
            buzzer=HIGH;&lt;br /&gt;
          }&lt;br /&gt;
          &lt;br /&gt;
        }  &lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
        &lt;br /&gt;
      //Execute alarm condition&lt;br /&gt;
      currentMillis = millis();&lt;br /&gt;
      if(buzzer)&lt;br /&gt;
      {&lt;br /&gt;
        digitalWrite(49,1);&lt;br /&gt;
        windDown(); // This loop should only be executed once and then skipped for at least 1 minute&lt;br /&gt;
        windDown_etime = currentMillis;&lt;br /&gt;
        Serial.println(&amp;quot;Buzzer Loop&amp;quot;);&lt;br /&gt;
      } else digitalWrite(49,0);        &lt;br /&gt;
      if (windDownFlag &amp;amp;&amp;amp; ((unsigned long)(currentMillis - windDown_etime) &amp;gt;= windDown_period))&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;post windDown windUp triggered&amp;quot;);&lt;br /&gt;
          windUp();&lt;br /&gt;
          windUp_etime = currentMillis;&lt;br /&gt;
        }&lt;br /&gt;
      if ((PANEL_VOLTS_READ &amp;gt;= dayLightVolt) &amp;amp;&amp;amp; (PANEL_AMPS_READ &amp;lt;= 1) &amp;amp;&amp;amp; (hotCellVolt &amp;lt;= windUpThreshold) &amp;amp;&amp;amp; ((unsigned long)(currentMillis - windUp_etime) &amp;gt;= windUp_period)) //Keep tweaking the controller to max&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;conditional windUp triggered&amp;quot;);&lt;br /&gt;
          windUp();&lt;br /&gt;
          windUp_etime = currentMillis;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
      if(unknownId != 0)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
        Serial.print(unknownId, HEX);&lt;br /&gt;
        Serial.println();&lt;br /&gt;
      }&lt;br /&gt;
     }&lt;br /&gt;
     else skip=LOW;    &lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      UpdateScreen(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode==0)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blues&lt;br /&gt;
    mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
    mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blacks&lt;br /&gt;
    mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,42 , 150, 191);   //Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,42 , 310, 191);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,234 , 150, 386);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170, 234 , 310, 386);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Lines&lt;br /&gt;
    mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
    mylcd.Draw_Line(11, 62, 149, 62);//Pack 1&lt;br /&gt;
    mylcd.Draw_Line(171, 62, 309, 62);//Pack 2&lt;br /&gt;
    mylcd.Draw_Line(11, 254, 149, 254);//Pack 3&lt;br /&gt;
    mylcd.Draw_Line(171, 254, 309, 254);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Reds &lt;br /&gt;
    mylcd.Set_Draw_color(RED);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,193 , 150, 214);//Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,193, 310, 214);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,384 , 150, 407);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170,384, 310, 407);//Pack 4&lt;br /&gt;
    //Title&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Set_Text_Mode(1);&lt;br /&gt;
    mylcd.Set_Text_Size(3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
    //Outline the screen&lt;br /&gt;
    mylcd.Set_Text_Size(2);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x04    (-)   x20    (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*10);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x06    (-)   x22    (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*22);&lt;br /&gt;
&lt;br /&gt;
    //credits, statusbar&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(int battery)&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(temperature[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
  &lt;br /&gt;
  if(c==7)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Set_Text_Mode(0);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
    mylcd.Print_Number_Float(sum[p], 3, xc+60, yc+22, '.', 0, ' ');&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  }&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw) // Convert the readings from the ADC to human readable&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit this loop will calculate it live but the look up table saves clock cycles&lt;br /&gt;
  //Supports Rounding&lt;br /&gt;
  //if( (raw*1.555)-26.0 - (int) ((raw*1.555)-26.0) &amp;gt;= 0.5)&lt;br /&gt;
  //  return (int)((raw*1.555)-25.0);&lt;br /&gt;
  //else&lt;br /&gt;
  //  return (int)((raw*1.555)-26.0);&lt;br /&gt;
  short static const table[256] = &lt;br /&gt;
                     {-26, -24,-23,-21,-20,-18,-17,-15,-14,-12,-10,-9,-7,-6,-4,-3,-1,&lt;br /&gt;
                      0,2,4,5,7,8,10,11,13,14,16,18,19,21,22,24,25,27,28,30,32,33,35,&lt;br /&gt;
                      36,38,39,41,42,44,46,47,49,50,52,53,55,56,58,60,61,63,64,66,67,&lt;br /&gt;
                      69,70,72,74,75,77,78,80,81,83,84,86,88,89,91,92,94,95,97,98,100,&lt;br /&gt;
                      102,103,105,106,108,109,111,112,114,116,117,119,120,122,123,125,&lt;br /&gt;
                      126,128,130,131,133,134,136,137,139,140,142,143,145,147,148,150,&lt;br /&gt;
                      151,153,154,156,157,159,161,162,164,165,167,168,170,171,173,175,&lt;br /&gt;
                      176,178,179,181,182,184,185,187,189,190,192,193,195,196,198,199,&lt;br /&gt;
                      201,203,204,206,207,209,210,212,213,215,217,218,220,221,223,224,&lt;br /&gt;
                      226,227,229,231,232,234,235,237,238,240,241,243,245,246,248,249,&lt;br /&gt;
                      251,252,254,255,257,259,260,262,263,265,266,268,269,271,273,274,&lt;br /&gt;
                      276,277,279,280,282,283,285,287,288,290,291,293,294,296,297,299,&lt;br /&gt;
                      301,302,304,305,307,308,310,311,313,315,316,318,319,321,322,324,&lt;br /&gt;
                      325,327,329,330,332,333,335,336,338,339,341,343,344,346,347,349,&lt;br /&gt;
                      350,352,353,355,357,358,360,361,363,364,366,367,369,371};&lt;br /&gt;
  return (int)table[raw]; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preTransmission() //Put RS485 into transmit mode by bringing the transmit and receive pins high&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 1);&lt;br /&gt;
  digitalWrite(MAX485_DE, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void postTransmission() //Put the RS485 into receive mode by bringing the transmit and receive pins low&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
}&lt;br /&gt;
void getControllerParams() // Hit the controller with a request for information&lt;br /&gt;
{&lt;br /&gt;
uint8_t result;&lt;br /&gt;
&lt;br /&gt;
  // Read 8 registers starting at 0x3100)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readInputRegisters(0x3100, 5);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    PANEL_VOLTS_READ = node.getResponseBuffer(PANEL_VOLTS); //Data slot 0&lt;br /&gt;
    PANEL_AMPS_READ = node.getResponseBuffer(PANEL_AMPS); //Data slot 1&lt;br /&gt;
    BATT_VOLTS_READ = node.getResponseBuffer(BATT_VOLTS); //Data slot 4 (2,3 skipped, not needed)&lt;br /&gt;
    Serial.print(&amp;quot;Panel volts: &amp;quot;);&lt;br /&gt;
    Serial.println((float)PANEL_VOLTS_READ/100.00);&lt;br /&gt;
    Serial.print(&amp;quot;Panel Amps: &amp;quot;);&lt;br /&gt;
    Serial.println((float)PANEL_AMPS_READ/100.00);&lt;br /&gt;
    Serial.print(&amp;quot;Battery volts: &amp;quot;);&lt;br /&gt;
    Serial.println((float)BATT_VOLTS_READ/100.00);&lt;br /&gt;
    Serial.println();&lt;br /&gt;
  } &lt;br /&gt;
  else { //If there's an error send it to the console&lt;br /&gt;
    Serial.print(&amp;quot;Reading controller parameters failed, error:&amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
  //delay(1000);&lt;br /&gt;
&lt;br /&gt;
  // Read 15 registers starting at 0x9000)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readHoldingRegisters(0x9000, 15);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    OVERVOLT_DISC_READ = node.getResponseBuffer(OVERVOLT_DISC);&lt;br /&gt;
    CHARGING_LIMIT_READ = node.getResponseBuffer(CHARGING_LIMIT);&lt;br /&gt;
    OVERVOLT_RECON_READ = node.getResponseBuffer(OVERVOLT_RECON);&lt;br /&gt;
    EQUILIBRIUM_CV_READ = node.getResponseBuffer(EQUILIBRIUM_CV);&lt;br /&gt;
    BOOST_CV_READ = node.getResponseBuffer(BOOST_CV);&lt;br /&gt;
    FLOAT_CV_READ = node.getResponseBuffer(FLOAT_CV);&lt;br /&gt;
    BOOST_RECON_READ = node.getResponseBuffer(BOOST_RECON);&lt;br /&gt;
    LOW_VOLT_RECON_READ = node.getResponseBuffer(LOW_VOLT);&lt;br /&gt;
    UNDERVOLT_RECOVERY_READ = node.getResponseBuffer(UNDERVOLT_RECOV);&lt;br /&gt;
    UNDERVOLT_WARNING_READ = node.getResponseBuffer(UNDERVOLT_WARN);&lt;br /&gt;
    LOW_VOLT_DISC_READ = node.getResponseBuffer(LOW_VOLT_DISC);&lt;br /&gt;
    DISCHARGE_LIMIT_READ = node.getResponseBuffer(DISCHARGE_LIMIT);&lt;br /&gt;
  } &lt;br /&gt;
  else {&lt;br /&gt;
    Serial.print(&amp;quot;The charging parameters failed to read, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //delay(2000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void windDown() // Quickly bring the controller charge voltage down so the hot cell will kalm&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  OVERVOLT_DISC_SETTO = BATT_VOLTS_READ + 50;&lt;br /&gt;
  CHARGING_LIMIT_SETTO = BATT_VOLTS_READ - 20;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  BOOST_CV_SETTO = BATT_VOLTS_READ - 40;&lt;br /&gt;
  FLOAT_CV_SETTO = BATT_VOLTS_READ - 50;&lt;br /&gt;
  BOOST_RECON_SETTO = BATT_VOLTS_READ - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
  windDownFlag = HIGH;&lt;br /&gt;
  Serial.println(&amp;quot;The controller is in wind down, settings will be readjusted in 5 minutes&amp;quot;);&lt;br /&gt;
  //Insert a timer to wind up in 2 minutes&lt;br /&gt;
}&lt;br /&gt;
void windUp() // Bring the controller charge voltage as close to max as possible&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  unsigned short difference = int((ALARM - hotCellVolt) * 100);&lt;br /&gt;
  unsigned short setvolt = BATT_VOLTS_READ + difference;&lt;br /&gt;
  OVERVOLT_DISC_SETTO = (setvolt + 50);&lt;br /&gt;
  CHARGING_LIMIT_SETTO = setvolt;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = setvolt - 10;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = setvolt - 20;&lt;br /&gt;
  BOOST_CV_SETTO = setvolt - 30;&lt;br /&gt;
  FLOAT_CV_SETTO = setvolt - 40;&lt;br /&gt;
  BOOST_RECON_SETTO = setvolt - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
  windDownFlag = LOW;&lt;br /&gt;
  Serial.println(&amp;quot;The controller has been adjusted up&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
void updateController() // Send new information to the controller&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  node.clearTransmitBuffer(); //Prepare the buffer with new data, clear and fill&lt;br /&gt;
  node.setTransmitBuffer(0, OVERVOLT_DISC_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(1, CHARGING_LIMIT_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(2, OVERVOLT_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(3, EQUILIBRIUM_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(4, BOOST_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(5, FLOAT_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(6, BOOST_RECON_SETTO);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  int result = (node.writeMultipleRegisters(0x9003,7)); //Yeet this new info to the controller&lt;br /&gt;
  if (result == 0) //Verify&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameters changed sucessfully&amp;quot;); // For Diagnostic console&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameter change failed, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
    Serial.print(&amp;quot;OVERVOLT_DISC_SETTO=&amp;quot;);&lt;br /&gt;
    Serial.println(OVERVOLT_DISC_SETTO,HEX);&lt;br /&gt;
    Serial.print(&amp;quot;CHARGING_LIMIT_SETTO=&amp;quot;);&lt;br /&gt;
    Serial.println(CHARGING_LIMIT_SETTO,HEX);&lt;br /&gt;
    Serial.print(&amp;quot;OVERVOLT_RECON_SETTO=&amp;quot;);&lt;br /&gt;
    Serial.println(OVERVOLT_RECON_SETTO,HEX);&lt;br /&gt;
    Serial.print(&amp;quot;EQUILIBRIUM_CV_SETTO=&amp;quot;);&lt;br /&gt;
    Serial.println(EQUILIBRIUM_CV_SETTO,HEX);&lt;br /&gt;
    Serial.print(&amp;quot;BOOST_CV_SETTO=&amp;quot;);&lt;br /&gt;
    Serial.println(BOOST_CV_SETTO,HEX);&lt;br /&gt;
    Serial.print(&amp;quot;FLOAT_CV_SETTO=&amp;quot;);&lt;br /&gt;
    Serial.println(FLOAT_CV_SETTO,HEX);&lt;br /&gt;
    Serial.print(&amp;quot;BOOST_RECON_SETTO=&amp;quot;);&lt;br /&gt;
    Serial.println(BOOST_RECON_SETTO,HEX);&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=97</id>
		<title>CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=97"/>
		<updated>2020-12-09T20:14:53Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */ New timer method implemented which should be failsafe&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
This was developed to test communication to the EPEVER AN Solar controller from the Arduino&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;mcp_can.h&amp;gt;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library http://www.lcdwiki.com/3.5inch_Arduino_Display-UNO&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
#include &amp;lt;ModbusMaster.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS                4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS                8     //Hazardous to modify&lt;br /&gt;
#define REFRESH                 1000   //Refresh rate display&lt;br /&gt;
#define ALARM                   3.640    //Alarm threshold&lt;br /&gt;
#define windUpDelay             300000 //Delay before controller attempts to increase the charge voltage, giving cells time to settle&lt;br /&gt;
#define windUpThreshold         3.550 //WindUp function will not call again until a cell reaches this voltage&lt;br /&gt;
&lt;br /&gt;
//Define the default values for your pack here, value *100, no decimal&lt;br /&gt;
#define def_OVERVOLT_DISC_VAL   2950&lt;br /&gt;
#define def_CHARGING_LIMIT_VAL  2860&lt;br /&gt;
#define def_OVERVOLT_RECON_VAL  2880&lt;br /&gt;
#define def_EQUILIBRIUM_CV_VAL  2830&lt;br /&gt;
#define def_BOOST_CV_VAL        2830&lt;br /&gt;
#define def_FLOAT_CV_VAL        2760        &lt;br /&gt;
#define def_BOOST_RECON_VAL     2640   &lt;br /&gt;
#define dayLightVolt            3500  &lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x1863&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RS485 converter connections&lt;br /&gt;
#define MAX485_DE   49&lt;br /&gt;
#define MAX485_RE   48&lt;br /&gt;
&lt;br /&gt;
// For Epever AN controller MODBUS read&lt;br /&gt;
#define PANEL_VOLTS     0x00&lt;br /&gt;
#define PANEL_AMPS      0x01&lt;br /&gt;
#define PANEL_POWER_L   0x02&lt;br /&gt;
#define PANEL_POWER_H   0x03&lt;br /&gt;
#define BATT_VOLTS      0x04&lt;br /&gt;
#define BATT_AMPS       0x05&lt;br /&gt;
#define BATT_POWER_L    0x06&lt;br /&gt;
#define BATT_POWER_H    0x07&lt;br /&gt;
#define OVERVOLT_DISC   0x00&lt;br /&gt;
#define CHARGING_LIMIT  0x01&lt;br /&gt;
#define OVERVOLT_RECON  0x02&lt;br /&gt;
#define EQUILIBRIUM_CV  0x03&lt;br /&gt;
#define BOOST_CV        0x04&lt;br /&gt;
#define FLOAT_CV        0x05&lt;br /&gt;
#define BOOST_RECON     0x06&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
unsigned long currentMillis;&lt;br /&gt;
&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
int temperature[NUMPACKS][NUMCELLS];&lt;br /&gt;
&lt;br /&gt;
//Pack Parameters - you will fill this info in once you find the CAN address of your packs. Only the last two numbers will be relevant&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
unsigned short hotCellVolt = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Variables for holding the solar controller's set values&lt;br /&gt;
unsigned short OVERVOLT_DISC_CURRENT;&lt;br /&gt;
unsigned short CHARGING_LIMIT_CURRENT;&lt;br /&gt;
unsigned short OVERVOLT_RECON_CURRENT;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_CURRENT;&lt;br /&gt;
unsigned short BOOST_CV_CURRENT;&lt;br /&gt;
unsigned short FLOAT_CV_CURRENT;&lt;br /&gt;
unsigned short BOOST_RECON_CURRENT;&lt;br /&gt;
bool is_Controller_default;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding register values from the controller&lt;br /&gt;
unsigned short PANEL_VOLTS_READ;&lt;br /&gt;
unsigned short PANEL_AMPS_READ;&lt;br /&gt;
unsigned short BATT_VOLTS_READ;&lt;br /&gt;
unsigned short BATT_AMPS_READ;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding values to be sent to the solar controller&lt;br /&gt;
unsigned short OVERVOLT_DISC_SETTO;&lt;br /&gt;
unsigned short CHARGING_LIMIT_SETTO;&lt;br /&gt;
unsigned short OVERVOLT_RECON_SETTO;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_CV_SETTO;&lt;br /&gt;
unsigned short FLOAT_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_RECON_SETTO;&lt;br /&gt;
&lt;br /&gt;
//Variables for working with the controller&lt;br /&gt;
bool windDownFlag = LOW;&lt;br /&gt;
//unsigned char bufA[10];&lt;br /&gt;
//unsigned char buf0[10];&lt;br /&gt;
//unsigned char buf3[10];&lt;br /&gt;
//unsigned char buf5[10];&lt;br /&gt;
//unsigned char buf20[10];&lt;br /&gt;
//unsigned char buf21[10];&lt;br /&gt;
//unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
//Low failure rate timer&lt;br /&gt;
const int windDown_period = 60000;&lt;br /&gt;
unsigned long windDown_etime = 0;&lt;br /&gt;
const long windUp_period = 600000;&lt;br /&gt;
unsigned long windUp_etime = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
// instantiate ModbusMaster object&lt;br /&gt;
ModbusMaster node;&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
long st, fn;&lt;br /&gt;
int q;  &lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temperature[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  pinMode(MAX485_RE, OUTPUT);&lt;br /&gt;
  pinMode(MAX485_DE, OUTPUT);&lt;br /&gt;
  // Init in receive mode&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
  &lt;br /&gt;
  // Modbus setup at 115200 baud&lt;br /&gt;
  Serial1.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  // EPEver Device ID 1&lt;br /&gt;
  node.begin(1, Serial1);&lt;br /&gt;
&lt;br /&gt;
  // Callbacks&lt;br /&gt;
  node.preTransmission(preTransmission);&lt;br /&gt;
  node.postTransmission(postTransmission);&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);        &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    Serial.print(&amp;quot;p&amp;quot;);//packet received&lt;br /&gt;
&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temperature[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temperature[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temperature[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temperature[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temperature code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temperature code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        //for(int i = 0; i&amp;lt;len; i++) {buf3[i] = buf[i];}&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500) ;//{for(int i = 0; i&amp;lt;len; i++){buf5[i] = buf[i];}}&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00) ;//{for(int i = 0; i&amp;lt;len; i++){bufA[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000) ;//{for(int i = 0; i&amp;lt;len; i++){buf0[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][7] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][6] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][5] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf20[i] = buf[i];} &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][4] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][3] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][2] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf21[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][1] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][0] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf22[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      hotCellVolt = 0;&lt;br /&gt;
      for(int i=0; i&amp;lt;NUMPACKS;i++) //Calculate a pack sum and check for hot cells&lt;br /&gt;
      {&lt;br /&gt;
        sum[i]=0.0;&lt;br /&gt;
        for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
        {&lt;br /&gt;
          sum[i] += voltage[i][j];&lt;br /&gt;
          if (voltage[i][j] &amp;gt; hotCellVolt)&lt;br /&gt;
            hotCellVolt = voltage[i][j];&lt;br /&gt;
          if(voltage[i][j]&amp;gt;=ALARM)&lt;br /&gt;
          {&lt;br /&gt;
            buzzer=HIGH;&lt;br /&gt;
          }&lt;br /&gt;
        }            &lt;br /&gt;
      }&lt;br /&gt;
        &lt;br /&gt;
      //Execute alarm condition&lt;br /&gt;
      currentMillis = millis();&lt;br /&gt;
      if(buzzer)&lt;br /&gt;
      {&lt;br /&gt;
        digitalWrite(49,1);&lt;br /&gt;
        windDown(); // This loop should only be executed once and then skipped for at least 1 minute&lt;br /&gt;
      } else digitalWrite(49,0);        &lt;br /&gt;
      if (windDownFlag &amp;amp;&amp;amp; ((unsigned long)(currentMillis - windDown_etime) &amp;gt;= windDown_period))&lt;br /&gt;
        windUp();&lt;br /&gt;
      if ((PANEL_VOLTS_READ &amp;gt;= dayLightVolt) &amp;amp;&amp;amp; (PANEL_AMPS_READ &amp;lt;= 1) &amp;amp;&amp;amp; (hotCellVolt &amp;lt;= windUpThreshold) &amp;amp;&amp;amp; ((unsigned long)(currentMillis - windUp_etime) &amp;gt;= windUp_period)) //Keep tweaking the controller to max&lt;br /&gt;
        windUp();&lt;br /&gt;
        &lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
      if(unknownId != 0)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
        Serial.print(unknownId, HEX);&lt;br /&gt;
        Serial.println();&lt;br /&gt;
      }&lt;br /&gt;
     }&lt;br /&gt;
     else skip=LOW;    &lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      UpdateScreen(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode==0)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blues&lt;br /&gt;
    mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
    mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blacks&lt;br /&gt;
    mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,42 , 150, 191);   //Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,42 , 310, 191);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,234 , 150, 386);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170, 234 , 310, 386);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Lines&lt;br /&gt;
    mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
    mylcd.Draw_Line(11, 62, 149, 62);//Pack 1&lt;br /&gt;
    mylcd.Draw_Line(171, 62, 309, 62);//Pack 2&lt;br /&gt;
    mylcd.Draw_Line(11, 254, 149, 254);//Pack 3&lt;br /&gt;
    mylcd.Draw_Line(171, 254, 309, 254);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Reds &lt;br /&gt;
    mylcd.Set_Draw_color(RED);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,193 , 150, 214);//Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,193, 310, 214);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,384 , 150, 407);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170,384, 310, 407);//Pack 4&lt;br /&gt;
    //Title&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Set_Text_Mode(1);&lt;br /&gt;
    mylcd.Set_Text_Size(3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
    //Outline the screen&lt;br /&gt;
    mylcd.Set_Text_Size(2);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x04    (-)   x20    (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*10);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x06    (-)   x22    (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*22);&lt;br /&gt;
&lt;br /&gt;
    //credits, statusbar&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(int battery)&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(temperature[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
  &lt;br /&gt;
  if(c==7)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Set_Text_Mode(0);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
    mylcd.Print_Number_Float(sum[p], 3, xc+60, yc+22, '.', 0, ' ');&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  }&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw) // Convert the readings from the ADC to human readable&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit this loop will calculate it live but the look up table saves clock cycles&lt;br /&gt;
  //Supports Rounding&lt;br /&gt;
  //if( (raw*1.555)-26.0 - (int) ((raw*1.555)-26.0) &amp;gt;= 0.5)&lt;br /&gt;
  //  return (int)((raw*1.555)-25.0);&lt;br /&gt;
  //else&lt;br /&gt;
  //  return (int)((raw*1.555)-26.0);&lt;br /&gt;
  short static const table[256] = &lt;br /&gt;
                     {-26, -24,-23,-21,-20,-18,-17,-15,-14,-12,-10,-9,-7,-6,-4,-3,-1,&lt;br /&gt;
                      0,2,4,5,7,8,10,11,13,14,16,18,19,21,22,24,25,27,28,30,32,33,35,&lt;br /&gt;
                      36,38,39,41,42,44,46,47,49,50,52,53,55,56,58,60,61,63,64,66,67,&lt;br /&gt;
                      69,70,72,74,75,77,78,80,81,83,84,86,88,89,91,92,94,95,97,98,100,&lt;br /&gt;
                      102,103,105,106,108,109,111,112,114,116,117,119,120,122,123,125,&lt;br /&gt;
                      126,128,130,131,133,134,136,137,139,140,142,143,145,147,148,150,&lt;br /&gt;
                      151,153,154,156,157,159,161,162,164,165,167,168,170,171,173,175,&lt;br /&gt;
                      176,178,179,181,182,184,185,187,189,190,192,193,195,196,198,199,&lt;br /&gt;
                      201,203,204,206,207,209,210,212,213,215,217,218,220,221,223,224,&lt;br /&gt;
                      226,227,229,231,232,234,235,237,238,240,241,243,245,246,248,249,&lt;br /&gt;
                      251,252,254,255,257,259,260,262,263,265,266,268,269,271,273,274,&lt;br /&gt;
                      276,277,279,280,282,283,285,287,288,290,291,293,294,296,297,299,&lt;br /&gt;
                      301,302,304,305,307,308,310,311,313,315,316,318,319,321,322,324,&lt;br /&gt;
                      325,327,329,330,332,333,335,336,338,339,341,343,344,346,347,349,&lt;br /&gt;
                      350,352,353,355,357,358,360,361,363,364,366,367,369,371};&lt;br /&gt;
  return (int)table[raw]; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preTransmission() //Put RS485 into transmit mode by bringing the transmit and receive pins high&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 1);&lt;br /&gt;
  digitalWrite(MAX485_DE, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void postTransmission() //Put the RS485 into receive mode by bringing the transmit and receive pins low&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
}&lt;br /&gt;
void getControllerParams() // Hit the controller with a request for information&lt;br /&gt;
{&lt;br /&gt;
uint8_t result;&lt;br /&gt;
&lt;br /&gt;
  // Read 8 registers starting at 0x3100)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readInputRegisters(0x3100, 5);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    PANEL_VOLTS_READ = node.getResponseBuffer(PANEL_VOLTS); //Data slot 0&lt;br /&gt;
    PANEL_AMPS_READ = node.getResponseBuffer(PANEL_AMPS); //Data slot 1&lt;br /&gt;
    BATT_VOLTS_READ = node.getResponseBuffer(BATT_VOLTS); //Data slot 4 (2,3 skipped, not needed)&lt;br /&gt;
  } &lt;br /&gt;
  else { //If there's an error send it to the console&lt;br /&gt;
    Serial.print(&amp;quot;Reading controller parameters failed, error:&amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
  //delay(1000);&lt;br /&gt;
&lt;br /&gt;
  // Read 7 registers starting at 0x9003)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readHoldingRegisters(0x9003, 7);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    OVERVOLT_DISC_CURRENT = node.getResponseBuffer(OVERVOLT_DISC);&lt;br /&gt;
    CHARGING_LIMIT_CURRENT = node.getResponseBuffer(CHARGING_LIMIT);&lt;br /&gt;
    OVERVOLT_RECON_CURRENT = node.getResponseBuffer(OVERVOLT_RECON);&lt;br /&gt;
    EQUILIBRIUM_CV_CURRENT = node.getResponseBuffer(EQUILIBRIUM_CV);&lt;br /&gt;
    BOOST_CV_CURRENT = node.getResponseBuffer(BOOST_CV);&lt;br /&gt;
    FLOAT_CV_CURRENT = node.getResponseBuffer(FLOAT_CV);&lt;br /&gt;
    BOOST_RECON_CURRENT = node.getResponseBuffer(BOOST_RECON);&lt;br /&gt;
  } &lt;br /&gt;
  else {&lt;br /&gt;
    Serial.print(&amp;quot;The charging parameters failed to read, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //delay(2000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void windDown() // Quickly bring the controller charge voltage down so the hot cell will kalm&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  OVERVOLT_DISC_SETTO = BATT_VOLTS_READ + 50;&lt;br /&gt;
  CHARGING_LIMIT_SETTO = BATT_VOLTS_READ - 20;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  BOOST_CV_SETTO = BATT_VOLTS_READ - 40;&lt;br /&gt;
  FLOAT_CV_SETTO = BATT_VOLTS_READ - 50;&lt;br /&gt;
  BOOST_RECON_SETTO = BATT_VOLTS_READ - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
  windDownFlag = HIGH;&lt;br /&gt;
  Serial.println(&amp;quot;The controller is in wind down, settings will be readjusted in 5 minutes&amp;quot;);&lt;br /&gt;
  //Insert a timer to wind up in 2 minutes&lt;br /&gt;
}&lt;br /&gt;
void windUp() // Bring the controller charge voltage as close to max as possible&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  unsigned short difference = int((ALARM - hotCellVolt) * 100);&lt;br /&gt;
  unsigned short setvolt = BATT_VOLTS_READ + difference;&lt;br /&gt;
  OVERVOLT_DISC_SETTO = (setvolt + 50);&lt;br /&gt;
  CHARGING_LIMIT_SETTO = setvolt;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = setvolt - 10;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = setvolt - 20;&lt;br /&gt;
  BOOST_CV_SETTO = setvolt - 30;&lt;br /&gt;
  FLOAT_CV_SETTO = setvolt - 40;&lt;br /&gt;
  BOOST_RECON_SETTO = setvolt - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
  windDownFlag = LOW;&lt;br /&gt;
  Serial.println(&amp;quot;The controller has been adjusted up&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
void updateController() // Send new information to the controller&lt;br /&gt;
{&lt;br /&gt;
  node.clearTransmitBuffer(); //Prepare the buffer with new data, clear and fill&lt;br /&gt;
  node.setTransmitBuffer(0, OVERVOLT_DISC_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(1, CHARGING_LIMIT_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(2, OVERVOLT_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(3, EQUILIBRIUM_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(4, BOOST_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(5, FLOAT_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(6, BOOST_RECON_SETTO);&lt;br /&gt;
  int result = (node.writeMultipleRegisters(9003,7)); //Yeet this new info to the controller&lt;br /&gt;
  if (result == 0) //Verify&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameters changed sucessfully&amp;quot;); // For Diagnostic console&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameter change failed, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=93</id>
		<title>CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=93"/>
		<updated>2020-12-09T18:50:13Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */  Last edit did not paste properly&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
This was developed to test communication to the EPEVER AN Solar controller from the Arduino&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;mcp_can.h&amp;gt;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library http://www.lcdwiki.com/3.5inch_Arduino_Display-UNO&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
#include &amp;lt;ModbusMaster.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS                4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS                8     //Hazardous to modify&lt;br /&gt;
#define REFRESH                 1000   //Refresh rate display&lt;br /&gt;
#define ALARM                   3.640    //Alarm threshold&lt;br /&gt;
#define windUpDelay             300000 //Delay before controller attempts to increase the charge voltage, giving cells time to settle&lt;br /&gt;
#define windUpThreshold         3.550 //WindUp function will not call again until a cell reaches this voltage&lt;br /&gt;
&lt;br /&gt;
//Define the default values for your pack here, value *100, no decimal&lt;br /&gt;
#define def_OVERVOLT_DISC_VAL   2950&lt;br /&gt;
#define def_CHARGING_LIMIT_VAL  2860&lt;br /&gt;
#define def_OVERVOLT_RECON_VAL  2880&lt;br /&gt;
#define def_EQUILIBRIUM_CV_VAL  2830&lt;br /&gt;
#define def_BOOST_CV_VAL        2830&lt;br /&gt;
#define def_FLOAT_CV_VAL        2760        &lt;br /&gt;
#define def_BOOST_RECON_VAL     2640   &lt;br /&gt;
#define dayLightVolt            3500  &lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x1863&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RS485 converter connections&lt;br /&gt;
#define MAX485_DE   49&lt;br /&gt;
#define MAX485_RE   48&lt;br /&gt;
&lt;br /&gt;
// For Epever AN controller MODBUS read&lt;br /&gt;
#define PANEL_VOLTS     0x00&lt;br /&gt;
#define PANEL_AMPS      0x01&lt;br /&gt;
#define PANEL_POWER_L   0x02&lt;br /&gt;
#define PANEL_POWER_H   0x03&lt;br /&gt;
#define BATT_VOLTS      0x04&lt;br /&gt;
#define BATT_AMPS       0x05&lt;br /&gt;
#define BATT_POWER_L    0x06&lt;br /&gt;
#define BATT_POWER_H    0x07&lt;br /&gt;
#define OVERVOLT_DISC   0x00&lt;br /&gt;
#define CHARGING_LIMIT  0x01&lt;br /&gt;
#define OVERVOLT_RECON  0x02&lt;br /&gt;
#define EQUILIBRIUM_CV  0x03&lt;br /&gt;
#define BOOST_CV        0x04&lt;br /&gt;
#define FLOAT_CV        0x05&lt;br /&gt;
#define BOOST_RECON     0x06&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
int temperature[NUMPACKS][NUMCELLS];&lt;br /&gt;
&lt;br /&gt;
//Pack Parameters - you will fill this info in once you find the CAN address of your packs. Only the last two numbers will be relevant&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
unsigned short hotCellVolt = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Variables for holding the solar controller's set values&lt;br /&gt;
unsigned short OVERVOLT_DISC_CURRENT;&lt;br /&gt;
unsigned short CHARGING_LIMIT_CURRENT;&lt;br /&gt;
unsigned short OVERVOLT_RECON_CURRENT;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_CURRENT;&lt;br /&gt;
unsigned short BOOST_CV_CURRENT;&lt;br /&gt;
unsigned short FLOAT_CV_CURRENT;&lt;br /&gt;
unsigned short BOOST_RECON_CURRENT;&lt;br /&gt;
bool is_Controller_default;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding register values from the controller&lt;br /&gt;
unsigned short PANEL_VOLTS_READ;&lt;br /&gt;
unsigned short PANEL_AMPS_READ;&lt;br /&gt;
unsigned short BATT_VOLTS_READ;&lt;br /&gt;
unsigned short BATT_AMPS_READ;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding values to be sent to the solar controller&lt;br /&gt;
unsigned short OVERVOLT_DISC_SETTO;&lt;br /&gt;
unsigned short CHARGING_LIMIT_SETTO;&lt;br /&gt;
unsigned short OVERVOLT_RECON_SETTO;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_CV_SETTO;&lt;br /&gt;
unsigned short FLOAT_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_RECON_SETTO;&lt;br /&gt;
&lt;br /&gt;
//Variables for working with the controller&lt;br /&gt;
bool windDownFlag = LOW;&lt;br /&gt;
//unsigned char bufA[10];&lt;br /&gt;
//unsigned char buf0[10];&lt;br /&gt;
//unsigned char buf3[10];&lt;br /&gt;
//unsigned char buf5[10];&lt;br /&gt;
//unsigned char buf20[10];&lt;br /&gt;
//unsigned char buf21[10];&lt;br /&gt;
//unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
// instantiate ModbusMaster object&lt;br /&gt;
ModbusMaster node;&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
long st, fn;&lt;br /&gt;
int q;  &lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temperature[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  pinMode(MAX485_RE, OUTPUT);&lt;br /&gt;
  pinMode(MAX485_DE, OUTPUT);&lt;br /&gt;
  // Init in receive mode&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
  &lt;br /&gt;
  // Modbus setup at 115200 baud&lt;br /&gt;
  Serial1.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  // EPEver Device ID 1&lt;br /&gt;
  node.begin(1, Serial1);&lt;br /&gt;
&lt;br /&gt;
  // Callbacks&lt;br /&gt;
  node.preTransmission(preTransmission);&lt;br /&gt;
  node.postTransmission(postTransmission);&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);        &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    Serial.print(&amp;quot;p&amp;quot;);//packet received&lt;br /&gt;
&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temperature[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temperature[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temperature[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temperature[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temperature code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temperature code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        //for(int i = 0; i&amp;lt;len; i++) {buf3[i] = buf[i];}&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500) ;//{for(int i = 0; i&amp;lt;len; i++){buf5[i] = buf[i];}}&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00) ;//{for(int i = 0; i&amp;lt;len; i++){bufA[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000) ;//{for(int i = 0; i&amp;lt;len; i++){buf0[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][7] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][6] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][5] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf20[i] = buf[i];} &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][4] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][3] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][2] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf21[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][1] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][0] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf22[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
        //TestTemp();&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        hotCellVolt = 0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          sum[i]=0.0;&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
            sum[i] += voltage[i][j];&lt;br /&gt;
            if (voltage[i][j] &amp;gt; hotCellVolt)&lt;br /&gt;
              hotCellVolt = voltage[i][j];&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)&lt;br /&gt;
            {&lt;br /&gt;
              buzzer=HIGH;&lt;br /&gt;
            }&lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
        {&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
          windDown(); // This loop should only be executed once and then skipped for at least 1 minute&lt;br /&gt;
        }&lt;br /&gt;
          &lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;;&lt;br /&gt;
        if (windDownFlag /*&amp;amp;&amp;amp; 5 minutes have passed*/)&lt;br /&gt;
          windUp();&lt;br /&gt;
        if ((PANEL_VOLTS_READ &amp;gt;= dayLightVolt) &amp;amp;&amp;amp; (PANEL_AMPS_READ == 0) &amp;amp;&amp;amp; (hotCellVolt &amp;lt;= windUpThreshold) /*&amp;amp;&amp;amp; (timer &amp;gt; 1 hour from windup)*/) //Keep tweaking the controller to max&lt;br /&gt;
          windUp();&lt;br /&gt;
        &lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen(0);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode==0)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blues&lt;br /&gt;
    mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
    mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blacks&lt;br /&gt;
    mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,42 , 150, 191);   //Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,42 , 310, 191);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,234 , 150, 386);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170, 234 , 310, 386);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Lines&lt;br /&gt;
    mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
    mylcd.Draw_Line(11, 62, 149, 62);//Pack 1&lt;br /&gt;
    mylcd.Draw_Line(171, 62, 309, 62);//Pack 2&lt;br /&gt;
    mylcd.Draw_Line(11, 254, 149, 254);//Pack 3&lt;br /&gt;
    mylcd.Draw_Line(171, 254, 309, 254);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Reds &lt;br /&gt;
    mylcd.Set_Draw_color(RED);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,193 , 150, 214);//Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,193, 310, 214);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,384 , 150, 407);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170,384, 310, 407);//Pack 4&lt;br /&gt;
    //Title&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Set_Text_Mode(1);&lt;br /&gt;
    mylcd.Set_Text_Size(3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
    //Outline the screen&lt;br /&gt;
    mylcd.Set_Text_Size(2);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x04    (-)   x20    (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*10);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x06    (-)   x22    (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*22);&lt;br /&gt;
&lt;br /&gt;
    //credits, statusbar&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(int battery)&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(temperature[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
  &lt;br /&gt;
  if(c==7)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Set_Text_Mode(0);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
    mylcd.Print_Number_Float(sum[p], 3, xc+60, yc+22, '.', 0, ' ');&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  }&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw) // Convert the readings from the ADC to human readable&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit this loop will calculate it live but the look up table saves clock cycles&lt;br /&gt;
  //Supports Rounding&lt;br /&gt;
  //if( (raw*1.555)-26.0 - (int) ((raw*1.555)-26.0) &amp;gt;= 0.5)&lt;br /&gt;
  //  return (int)((raw*1.555)-25.0);&lt;br /&gt;
  //else&lt;br /&gt;
  //  return (int)((raw*1.555)-26.0);&lt;br /&gt;
  short static const table[256] = &lt;br /&gt;
                     {-26, -24,-23,-21,-20,-18,-17,-15,-14,-12,-10,-9,-7,-6,-4,-3,-1,&lt;br /&gt;
                      0,2,4,5,7,8,10,11,13,14,16,18,19,21,22,24,25,27,28,30,32,33,35,&lt;br /&gt;
                      36,38,39,41,42,44,46,47,49,50,52,53,55,56,58,60,61,63,64,66,67,&lt;br /&gt;
                      69,70,72,74,75,77,78,80,81,83,84,86,88,89,91,92,94,95,97,98,100,&lt;br /&gt;
                      102,103,105,106,108,109,111,112,114,116,117,119,120,122,123,125,&lt;br /&gt;
                      126,128,130,131,133,134,136,137,139,140,142,143,145,147,148,150,&lt;br /&gt;
                      151,153,154,156,157,159,161,162,164,165,167,168,170,171,173,175,&lt;br /&gt;
                      176,178,179,181,182,184,185,187,189,190,192,193,195,196,198,199,&lt;br /&gt;
                      201,203,204,206,207,209,210,212,213,215,217,218,220,221,223,224,&lt;br /&gt;
                      226,227,229,231,232,234,235,237,238,240,241,243,245,246,248,249,&lt;br /&gt;
                      251,252,254,255,257,259,260,262,263,265,266,268,269,271,273,274,&lt;br /&gt;
                      276,277,279,280,282,283,285,287,288,290,291,293,294,296,297,299,&lt;br /&gt;
                      301,302,304,305,307,308,310,311,313,315,316,318,319,321,322,324,&lt;br /&gt;
                      325,327,329,330,332,333,335,336,338,339,341,343,344,346,347,349,&lt;br /&gt;
                      350,352,353,355,357,358,360,361,363,364,366,367,369,371};&lt;br /&gt;
  return (int)table[raw]; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preTransmission() //Put RS485 into transmit mode by bringing the transmit and receive pins high&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 1);&lt;br /&gt;
  digitalWrite(MAX485_DE, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void postTransmission() //Put the RS485 into receive mode by bringing the transmit and receive pins low&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
}&lt;br /&gt;
void getControllerParams() // Hit the controller with a request for information&lt;br /&gt;
{&lt;br /&gt;
uint8_t result;&lt;br /&gt;
&lt;br /&gt;
  // Read 8 registers starting at 0x3100)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readInputRegisters(0x3100, 5);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    PANEL_VOLTS_READ = node.getResponseBuffer(PANEL_VOLTS); //Data slot 0&lt;br /&gt;
    PANEL_AMPS_READ = node.getResponseBuffer(PANEL_AMPS); //Data slot 1&lt;br /&gt;
    BATT_VOLTS_READ = node.getResponseBuffer(BATT_VOLTS); //Data slot 4 (2,3 skipped, not needed)&lt;br /&gt;
  } &lt;br /&gt;
  else { //If there's an error send it to the console&lt;br /&gt;
    Serial.print(&amp;quot;Reading controller parameters failed, error:&amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
  //delay(1000);&lt;br /&gt;
&lt;br /&gt;
  // Read 7 registers starting at 0x9003)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readHoldingRegisters(0x9003, 7);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    OVERVOLT_DISC_CURRENT = node.getResponseBuffer(OVERVOLT_DISC);&lt;br /&gt;
    CHARGING_LIMIT_CURRENT = node.getResponseBuffer(CHARGING_LIMIT);&lt;br /&gt;
    OVERVOLT_RECON_CURRENT = node.getResponseBuffer(OVERVOLT_RECON);&lt;br /&gt;
    EQUILIBRIUM_CV_CURRENT = node.getResponseBuffer(EQUILIBRIUM_CV);&lt;br /&gt;
    BOOST_CV_CURRENT = node.getResponseBuffer(BOOST_CV);&lt;br /&gt;
    FLOAT_CV_CURRENT = node.getResponseBuffer(FLOAT_CV);&lt;br /&gt;
    BOOST_RECON_CURRENT = node.getResponseBuffer(BOOST_RECON);&lt;br /&gt;
  } &lt;br /&gt;
  else {&lt;br /&gt;
    Serial.print(&amp;quot;The charging parameters failed to read, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //delay(2000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void windDown() // Quickly bring the controller charge voltage down so the hot cell will kalm&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  OVERVOLT_DISC_SETTO = BATT_VOLTS_READ + 50;&lt;br /&gt;
  CHARGING_LIMIT_SETTO = BATT_VOLTS_READ - 20;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  BOOST_CV_SETTO = BATT_VOLTS_READ - 40;&lt;br /&gt;
  FLOAT_CV_SETTO = BATT_VOLTS_READ - 50;&lt;br /&gt;
  BOOST_RECON_SETTO = BATT_VOLTS_READ - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
  windDownFlag = HIGH;&lt;br /&gt;
  Serial.println(&amp;quot;The controller is in wind down, settings will be readjusted in 5 minutes&amp;quot;);&lt;br /&gt;
  //Insert a timer to wind up in 2 minutes&lt;br /&gt;
}&lt;br /&gt;
void windUp() // Bring the controller charge voltage as close to max as possible&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  unsigned short difference = int((ALARM - hotCellVolt) * 100);&lt;br /&gt;
  unsigned short setvolt = BATT_VOLTS_READ + difference;&lt;br /&gt;
  OVERVOLT_DISC_SETTO = (setvolt + 50);&lt;br /&gt;
  CHARGING_LIMIT_SETTO = setvolt;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = setvolt - 10;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = setvolt - 20;&lt;br /&gt;
  BOOST_CV_SETTO = setvolt - 30;&lt;br /&gt;
  FLOAT_CV_SETTO = setvolt - 40;&lt;br /&gt;
  BOOST_RECON_SETTO = setvolt - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
  windDownFlag = LOW;&lt;br /&gt;
  Serial.println(&amp;quot;The controller has been adjusted up&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
void updateController() // Send new information to the controller&lt;br /&gt;
{&lt;br /&gt;
  node.clearTransmitBuffer(); //Prepare the buffer with new data, clear and fill&lt;br /&gt;
  node.setTransmitBuffer(0, OVERVOLT_DISC_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(1, CHARGING_LIMIT_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(2, OVERVOLT_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(3, EQUILIBRIUM_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(4, BOOST_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(5, FLOAT_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(6, BOOST_RECON_SETTO);&lt;br /&gt;
  int result = (node.writeMultipleRegisters(9003,7)); //Yeet this new info to the controller&lt;br /&gt;
  if (result == 0) //Verify&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameters changed sucessfully&amp;quot;); // For Diagnostic console&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameter change failed, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=92</id>
		<title>CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=92"/>
		<updated>2020-12-09T18:43:48Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
This was developed to test communication to the EPEVER AN Solar controller from the Arduino&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;mcp_can.h&amp;gt;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library http://www.lcdwiki.com/3.5inch_Arduino_Display-UNO&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
#include &amp;lt;ModbusMaster.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS                4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS                8     //Hazardous to modify&lt;br /&gt;
#define REFRESH                 1000   //Refresh rate display&lt;br /&gt;
#define ALARM                   3.640    //Alarm threshold&lt;br /&gt;
#define windUpDelay             300000 //Delay before controller attempts to increase the charge voltage, giving cells time to settle&lt;br /&gt;
#define windUpThreshold         3.550 //WindUp function will not call again until a cell reaches this voltage&lt;br /&gt;
&lt;br /&gt;
//Define the default values for your pack here, value *100, no decimal&lt;br /&gt;
#define def_OVERVOLT_DISC_VAL   2950&lt;br /&gt;
#define def_CHARGING_LIMIT_VAL  2860&lt;br /&gt;
#define def_OVERVOLT_RECON_VAL  2880&lt;br /&gt;
#define def_EQUILIBRIUM_CV_VAL  2830&lt;br /&gt;
#define def_BOOST_CV_VAL        2830&lt;br /&gt;
#define def_FLOAT_CV_VAL        2760        &lt;br /&gt;
#define def_BOOST_RECON_VAL     2640   &lt;br /&gt;
#define dayLightVolt            3500  &lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x1863&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RS485 converter connections&lt;br /&gt;
#define MAX485_DE   49&lt;br /&gt;
#define MAX485_RE   48&lt;br /&gt;
&lt;br /&gt;
// For Epever AN controller MODBUS read&lt;br /&gt;
#define PANEL_VOLTS     0x00&lt;br /&gt;
#define PANEL_AMPS      0x01&lt;br /&gt;
#define PANEL_POWER_L   0x02&lt;br /&gt;
#define PANEL_POWER_H   0x03&lt;br /&gt;
#define BATT_VOLTS      0x04&lt;br /&gt;
#define BATT_AMPS       0x05&lt;br /&gt;
#define BATT_POWER_L    0x06&lt;br /&gt;
#define BATT_POWER_H    0x07&lt;br /&gt;
#define OVERVOLT_DISC   0x00&lt;br /&gt;
#define CHARGING_LIMIT  0x01&lt;br /&gt;
#define OVERVOLT_RECON  0x02&lt;br /&gt;
#define EQUILIBRIUM_CV  0x03&lt;br /&gt;
#define BOOST_CV        0x04&lt;br /&gt;
#define FLOAT_CV        0x05&lt;br /&gt;
#define BOOST_RECON     0x06&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
int temperature[NUMPACKS][NUMCELLS];&lt;br /&gt;
&lt;br /&gt;
//Pack Parameters - you will fill this info in once you find the CAN address of your packs. Only the last two numbers will be relevant&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
unsigned short hotCellVolt = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//Variables for holding the solar controller's set values&lt;br /&gt;
unsigned short OVERVOLT_DISC_CURRENT;&lt;br /&gt;
unsigned short CHARGING_LIMIT_CURRENT;&lt;br /&gt;
unsigned short OVERVOLT_RECON_CURRENT;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_CURRENT;&lt;br /&gt;
unsigned short BOOST_CV_CURRENT;&lt;br /&gt;
unsigned short FLOAT_CV_CURRENT;&lt;br /&gt;
unsigned short BOOST_RECON_CURRENT;&lt;br /&gt;
bool is_Controller_default;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding register values from the controller&lt;br /&gt;
unsigned short PANEL_VOLTS_READ;&lt;br /&gt;
unsigned short PANEL_AMPS_READ;&lt;br /&gt;
unsigned short BATT_VOLTS_READ;&lt;br /&gt;
unsigned short BATT_AMPS_READ;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding values to be sent to the solar controller&lt;br /&gt;
unsigned short OVERVOLT_DISC_SETTO;&lt;br /&gt;
unsigned short CHARGING_LIMIT_SETTO;&lt;br /&gt;
unsigned short OVERVOLT_RECON_SETTO;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_CV_SETTO;&lt;br /&gt;
unsigned short FLOAT_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_RECON_SETTO;&lt;br /&gt;
&lt;br /&gt;
//Variables for working with the controller&lt;br /&gt;
bool windDownFlag = LOW;&lt;br /&gt;
//unsigned char bufA[10];&lt;br /&gt;
//unsigned char buf0[10];&lt;br /&gt;
//unsigned char buf3[10];&lt;br /&gt;
//unsigned char buf5[10];&lt;br /&gt;
//unsigned char buf20[10];&lt;br /&gt;
//unsigned char buf21[10];&lt;br /&gt;
//unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
// instantiate ModbusMaster object&lt;br /&gt;
ModbusMaster node;&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
long st, fn;&lt;br /&gt;
int q;  &lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temperature[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  pinMode(MAX485_RE, OUTPUT);&lt;br /&gt;
  pinMode(MAX485_DE, OUTPUT);&lt;br /&gt;
  // Init in receive mode&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
  &lt;br /&gt;
  // Modbus setup at 115200 baud&lt;br /&gt;
  Serial1.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  // EPEver Device ID 1&lt;br /&gt;
  node.begin(1, Serial1);&lt;br /&gt;
&lt;br /&gt;
  // Callbacks&lt;br /&gt;
  node.preTransmission(preTransmission);&lt;br /&gt;
  node.postTransmission(postTransmission);&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);        &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    Serial.print(&amp;quot;p&amp;quot;);//packet received&lt;br /&gt;
&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temperature[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temperature[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temperature[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temperature[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temperature code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temperature code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        //for(int i = 0; i&amp;lt;len; i++) {buf3[i] = buf[i];}&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500) ;//{for(int i = 0; i&amp;lt;len; i++){buf5[i] = buf[i];}}&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00) ;//{for(int i = 0; i&amp;lt;len; i++){bufA[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000) ;//{for(int i = 0; i&amp;lt;len; i++){buf0[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][7] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][6] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][5] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf20[i] = buf[i];} &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][4] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][3] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][2] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf21[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][1] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][0] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf22[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
        //TestTemp();&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        hotCellVolt = 0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          sum[i]=0.0;&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
            sum[i] += voltage[i][j];&lt;br /&gt;
            if (voltage[i][j] &amp;gt; hotCellVolt)&lt;br /&gt;
              hotCellVolt = voltage[i][j];&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)&lt;br /&gt;
            {&lt;br /&gt;
              buzzer=HIGH;&lt;br /&gt;
            }&lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
        {&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
          windDown(); // This loop should only be executed once and then skipped for at least 1 minute&lt;br /&gt;
        }&lt;br /&gt;
          &lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;;&lt;br /&gt;
        if (windDownFlag /*&amp;amp;&amp;amp; 5 minutes have passed*/)&lt;br /&gt;
          windUp();&lt;br /&gt;
        if ((PANEL_VOLTS_READ &amp;gt;= dayLightVolt) &amp;amp;&amp;amp; (PANEL_AMPS_READ == 0) &amp;amp;&amp;amp; (hotCellVolt &amp;lt;= windUpThreshold) /*&amp;amp;&amp;amp; (timer &amp;gt; 1 hour from windup)*/) //Keep tweaking the controller to max&lt;br /&gt;
          windUp();&lt;br /&gt;
        &lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen(0);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode==0)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blues&lt;br /&gt;
    mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
    mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blacks&lt;br /&gt;
    mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,42 , 150, 191);   //Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,42 , 310, 191);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,234 , 150, 386);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170, 234 , 310, 386);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Lines&lt;br /&gt;
    mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
    mylcd.Draw_Line(11, 62, 149, 62);//Pack 1&lt;br /&gt;
    mylcd.Draw_Line(171, 62, 309, 62);//Pack 2&lt;br /&gt;
    mylcd.Draw_Line(11, 254, 149, 254);//Pack 3&lt;br /&gt;
    mylcd.Draw_Line(171, 254, 309, 254);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Reds &lt;br /&gt;
    mylcd.Set_Draw_color(RED);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,193 , 150, 214);//Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,193, 310, 214);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,384 , 150, 407);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170,384, 310, 407);//Pack 4&lt;br /&gt;
    //Title&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Set_Text_Mode(1);&lt;br /&gt;
    mylcd.Set_Text_Size(3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
    //Outline the screen&lt;br /&gt;
    mylcd.Set_Text_Size(2);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x04    (-)   x20    (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*10);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x06    (-)   x22    (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*22);&lt;br /&gt;
&lt;br /&gt;
    //credits, statusbar&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(int battery)&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(temperature[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
  &lt;br /&gt;
  if(c==7)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Set_Text_Mode(0);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
    mylcd.Print_Number_Float(sum[p], 3, xc+60, yc+22, '.', 0, ' ');&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  }&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw) // Convert the readings from the ADC to human readable&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit this loop will calculate it live but the look up table saves clock cycles&lt;br /&gt;
  //Supports Rounding&lt;br /&gt;
  //if( (raw*1.555)-26.0 - (int) ((raw*1.555)-26.0) &amp;gt;= 0.5)&lt;br /&gt;
  //  return (int)((raw*1.555)-25.0);&lt;br /&gt;
  //else&lt;br /&gt;
  //  return (int)((raw*1.555)-26.0);&lt;br /&gt;
  short static const table[256] = &lt;br /&gt;
                     {-26, -24,-23,-21,-20,-18,-17,-15,-14,-12,-10,-9,-7,-6,-4,-3,-1,&lt;br /&gt;
                      0,2,4,5,7,8,10,11,13,14,16,18,19,21,22,24,25,27,28,30,32,33,35,&lt;br /&gt;
                      36,38,39,41,42,44,46,47,49,50,52,53,55,56,58,60,61,63,64,66,67,&lt;br /&gt;
                      69,70,72,74,75,77,78,80,81,83,84,86,88,89,91,92,94,95,97,98,100,&lt;br /&gt;
                      102,103,105,106,108,109,111,112,114,116,117,119,120,122,123,125,&lt;br /&gt;
                      126,128,130,131,133,134,136,137,139,140,142,143,145,147,148,150,&lt;br /&gt;
                      151,153,154,156,157,159,161,162,164,165,167,168,170,171,173,175,&lt;br /&gt;
                      176,178,179,181,182,184,185,187,189,190,192,193,195,196,198,199,&lt;br /&gt;
                      201,203,204,206,207,209,210,212,213,215,217,218,220,221,223,224,&lt;br /&gt;
                      226,227,229,231,232,234,235,237,238,240,241,243,245,246,248,249,&lt;br /&gt;
                      251,252,254,255,257,259,260,262,263,265,266,268,269,271,273,274,&lt;br /&gt;
                      276,277,279,280,282,283,285,287,288,290,291,293,294,296,297,299,&lt;br /&gt;
                      301,302,304,305,307,308,310,311,313,315,316,318,319,321,322,324,&lt;br /&gt;
                      325,327,329,330,332,333,335,336,338,339,341,343,344,346,347,349,&lt;br /&gt;
                      350,352,353,355,357,358,360,361,363,364,366,367,369,371};&lt;br /&gt;
  return (int)table[raw]; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preTransmission() //Put RS485 into transmit mode by bringing the transmit and receive pins high&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 1);&lt;br /&gt;
  digitalWrite(MAX485_DE, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void postTransmission() //Put the RS485 into receive mode by bringing the transmit and receive pins low&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
}&lt;br /&gt;
void getControllerParams() // Hit the controller with a request for information&lt;br /&gt;
{&lt;br /&gt;
uint8_t result;&lt;br /&gt;
&lt;br /&gt;
  // Read 8 registers starting at 0x3100)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readInputRegisters(0x3100, 5);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    PANEL_VOLTS_READ = node.getResponseBuffer(PANEL_VOLTS); //Data slot 0&lt;br /&gt;
    PANEL_AMPS_READ = node.getResponseBuffer(PANEL_AMPS); //Data slot 1&lt;br /&gt;
    BATT_VOLTS_READ = node.getResponseBuffer(BATT_VOLTS); //Data slot 4 (2,3 skipped, not needed)&lt;br /&gt;
  } &lt;br /&gt;
  else { //If there's an error send it to the console&lt;br /&gt;
    Serial.print(&amp;quot;Reading controller parameters failed, error:&amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
  //delay(1000);&lt;br /&gt;
&lt;br /&gt;
  // Read 7 registers starting at 0x9003)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readHoldingRegisters(0x9003, 7);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    OVERVOLT_DISC_CURRENT = node.getResponseBuffer(OVERVOLT_DISC);&lt;br /&gt;
    CHARGING_LIMIT_CURRENT = node.getResponseBuffer(CHARGING_LIMIT);&lt;br /&gt;
    OVERVOLT_RECON_CURRENT = node.getResponseBuffer(OVERVOLT_RECON);&lt;br /&gt;
    EQUILIBRIUM_CV_CURRENT = node.getResponseBuffer(EQUILIBRIUM_CV);&lt;br /&gt;
    BOOST_CV_CURRENT = node.getResponseBuffer(BOOST_CV);&lt;br /&gt;
    FLOAT_CV_CURRENT = node.getResponseBuffer(FLOAT_CV);&lt;br /&gt;
    BOOST_RECON_CURRENT = node.getResponseBuffer(BOOST_RECON);&lt;br /&gt;
  } &lt;br /&gt;
  else {&lt;br /&gt;
    Serial.print(&amp;quot;Miss read, ret val:&amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //delay(2000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void windDown() // Quickly bring the controller charge voltage down so the hot cell will kalm&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  OVERVOLT_DISC_SETTO = BATT_VOLTS_READ + 50;&lt;br /&gt;
  CHARGING_LIMIT_SETTO = BATT_VOLTS_READ - 20;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  BOOST_CV_SETTO = BATT_VOLTS_READ - 40;&lt;br /&gt;
  FLOAT_CV_SETTO = BATT_VOLTS_READ - 50;&lt;br /&gt;
  BOOST_RECON_SETTO = BATT_VOLTS_READ - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
  windDownFlag = HIGH;&lt;br /&gt;
  Serial.println(&amp;quot;The controller is in wind down, settings will be readjusted in 5 minutes&amp;quot;);&lt;br /&gt;
  //Insert a timer to wind up in 2 minutes&lt;br /&gt;
}&lt;br /&gt;
void windUp() // Bring the controller charge voltage as close to max as possible&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  unsigned short difference = int((ALARM - hotCellVolt) * 100);&lt;br /&gt;
  unsigned short setvolt = BATT_VOLTS_READ + difference;&lt;br /&gt;
  OVERVOLT_DISC_SETTO = (setvolt + 50);&lt;br /&gt;
  CHARGING_LIMIT_SETTO = setvolt;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = setvolt - 10;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = setvolt - 20;&lt;br /&gt;
  BOOST_CV_SETTO = setvolt - 30;&lt;br /&gt;
  FLOAT_CV_SETTO = setvolt - 40;&lt;br /&gt;
  BOOST_RECON_SETTO = setvolt - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
  windDownFlag = LOW;&lt;br /&gt;
  Serial.println(&amp;quot;The controller has been adjusted up&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
void updateController() // Send new information to the controller&lt;br /&gt;
{&lt;br /&gt;
  node.clearTransmitBuffer(); //Prepare the buffer with new data, clear and fill&lt;br /&gt;
  node.setTransmitBuffer(0, OVERVOLT_DISC_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(1, CHARGING_LIMIT_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(2, OVERVOLT_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(3, EQUILIBRIUM_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(4, BOOST_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(5, FLOAT_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(6, BOOST_RECON_SETTO);&lt;br /&gt;
  int result = (node.writeMultipleRegisters(9003,7)); //Yeet this new info to the controller&lt;br /&gt;
  if (result == 0) //Verify&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameters changed sucessfully&amp;quot;); // For Diagnostic console&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameter change failed, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=91</id>
		<title>CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=91"/>
		<updated>2020-12-09T17:39:10Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
This was developed to test communication to the EPEVER AN Solar controller from the Arduino&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;mcp_can.h&amp;gt;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library http://www.lcdwiki.com/3.5inch_Arduino_Display-UNO&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
#include &amp;lt;ModbusMaster.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS 4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS 8     //Hazardous to modify&lt;br /&gt;
#define REFRESH 1000   //Refresh rate display&lt;br /&gt;
#define ALARM 3.640    //Alarm threshold&lt;br /&gt;
#define windUpDelay 300000 //Delay before controller attempts to increase the charge voltage, giving cells time to settle&lt;br /&gt;
&lt;br /&gt;
//Define the default values for your pack here, value *100, no decimal&lt;br /&gt;
#define def_OVERVOLT_DISC_VAL   2950&lt;br /&gt;
#define def_CHARGING_LIMIT_VAL  2860&lt;br /&gt;
#define def_OVERVOLT_RECON_VAL  2880&lt;br /&gt;
#define def_EQUILIBRIUM_CV_VAL  2830&lt;br /&gt;
#define def_BOOST_CV_VAL        2830&lt;br /&gt;
#define def_FLOAT_CV_VAL        2760        &lt;br /&gt;
#define def_BOOST_RECON_VAL     2640        &lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x1863&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RS485 converter connections&lt;br /&gt;
#define MAX485_DE   49&lt;br /&gt;
#define MAX485_RE   48&lt;br /&gt;
&lt;br /&gt;
// For Epever AN controller MODBUS read&lt;br /&gt;
#define PANEL_VOLTS     0x00&lt;br /&gt;
#define PANEL_AMPS      0x01&lt;br /&gt;
#define PANEL_POWER_L   0x02&lt;br /&gt;
#define PANEL_POWER_H   0x03&lt;br /&gt;
#define BATT_VOLTS      0x04&lt;br /&gt;
#define BATT_AMPS       0x05&lt;br /&gt;
#define BATT_POWER_L    0x06&lt;br /&gt;
#define BATT_POWER_H    0x07&lt;br /&gt;
#define OVERVOLT_DISC   0x00&lt;br /&gt;
#define CHARGING_LIMIT  0x01&lt;br /&gt;
#define OVERVOLT_RECON  0x02&lt;br /&gt;
#define EQUILIBRIUM_CV  0x03&lt;br /&gt;
#define BOOST_CV        0x04&lt;br /&gt;
#define FLOAT_CV        0x05&lt;br /&gt;
#define BOOST_RECON     0x06&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
int temperature[NUMPACKS][NUMCELLS];&lt;br /&gt;
&lt;br /&gt;
//Pack Parameters - you will fill this info in once you find the CAN address of your packs. Only the last two numbers will be relevant&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
unsigned short hotCellVolt = 0;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding the solar controller's set values&lt;br /&gt;
unsigned short OVERVOLT_DISC_CURRENT;&lt;br /&gt;
unsigned short CHARGING_LIMIT_CURRENT;&lt;br /&gt;
unsigned short OVERVOLT_RECON_CURRENT;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_CURRENT;&lt;br /&gt;
unsigned short BOOST_CV_CURRENT;&lt;br /&gt;
unsigned short FLOAT_CV_CURRENT;&lt;br /&gt;
unsigned short BOOST_RECON_CURRENT;&lt;br /&gt;
bool is_Controller_default;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding register values from the controller&lt;br /&gt;
unsigned short PANEL_VOLTS_READ;&lt;br /&gt;
unsigned short PANEL_AMPS_READ;&lt;br /&gt;
unsigned short BATT_VOLTS_READ;&lt;br /&gt;
unsigned short BATT_AMPS_READ;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding values to be sent to the solar controller&lt;br /&gt;
unsigned short OVERVOLT_DISC_SETTO;&lt;br /&gt;
unsigned short CHARGING_LIMIT_SETTO;&lt;br /&gt;
unsigned short OVERVOLT_RECON_SETTO;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_CV_SETTO;&lt;br /&gt;
unsigned short FLOAT_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_RECON_SETTO;&lt;br /&gt;
&lt;br /&gt;
//unsigned char bufA[10];&lt;br /&gt;
//unsigned char buf0[10];&lt;br /&gt;
//unsigned char buf3[10];&lt;br /&gt;
//unsigned char buf5[10];&lt;br /&gt;
//unsigned char buf20[10];&lt;br /&gt;
//unsigned char buf21[10];&lt;br /&gt;
//unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
// instantiate ModbusMaster object&lt;br /&gt;
ModbusMaster node;&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
long st, fn;&lt;br /&gt;
int q;  &lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temperature[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  pinMode(MAX485_RE, OUTPUT);&lt;br /&gt;
  pinMode(MAX485_DE, OUTPUT);&lt;br /&gt;
  // Init in receive mode&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
  &lt;br /&gt;
  // Modbus setup at 115200 baud&lt;br /&gt;
  Serial1.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  // EPEver Device ID 1&lt;br /&gt;
  node.begin(1, Serial1);&lt;br /&gt;
&lt;br /&gt;
  // Callbacks&lt;br /&gt;
  node.preTransmission(preTransmission);&lt;br /&gt;
  node.postTransmission(postTransmission);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);        &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    Serial.print(&amp;quot;p&amp;quot;);//packet received&lt;br /&gt;
&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temperature[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temperature[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temperature[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temperature[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temperature code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temperature code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        //for(int i = 0; i&amp;lt;len; i++) {buf3[i] = buf[i];}&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500) ;//{for(int i = 0; i&amp;lt;len; i++){buf5[i] = buf[i];}}&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00) ;//{for(int i = 0; i&amp;lt;len; i++){bufA[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000) ;//{for(int i = 0; i&amp;lt;len; i++){buf0[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][7] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][6] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][5] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf20[i] = buf[i];} &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][4] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][3] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][2] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf21[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][1] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][0] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf22[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
        //TestTemp();&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        hotCellVolt = 0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          sum[i]=0.0;&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
            sum[i] += voltage[i][j];&lt;br /&gt;
            if (voltage[i][j] &amp;gt; hotCellVolt)&lt;br /&gt;
              hotCellVolt = voltage[i][j];&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)&lt;br /&gt;
            {&lt;br /&gt;
              buzzer=HIGH;&lt;br /&gt;
            }&lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
        {&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
          windDown();&lt;br /&gt;
        }&lt;br /&gt;
          &lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;&lt;br /&gt;
        &lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen(0);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode==0)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blues&lt;br /&gt;
    mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
    mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blacks&lt;br /&gt;
    mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,42 , 150, 191);   //Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,42 , 310, 191);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,234 , 150, 386);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170, 234 , 310, 386);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Lines&lt;br /&gt;
    mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
    mylcd.Draw_Line(11, 62, 149, 62);//Pack 1&lt;br /&gt;
    mylcd.Draw_Line(171, 62, 309, 62);//Pack 2&lt;br /&gt;
    mylcd.Draw_Line(11, 254, 149, 254);//Pack 3&lt;br /&gt;
    mylcd.Draw_Line(171, 254, 309, 254);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Reds &lt;br /&gt;
    mylcd.Set_Draw_color(RED);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,193 , 150, 214);//Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,193, 310, 214);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,384 , 150, 407);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170,384, 310, 407);//Pack 4&lt;br /&gt;
    //Title&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Set_Text_Mode(1);&lt;br /&gt;
    mylcd.Set_Text_Size(3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
    //Outline the screen&lt;br /&gt;
    mylcd.Set_Text_Size(2);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x04    (-)   x20    (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*10);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x06    (-)   x22    (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*22);&lt;br /&gt;
&lt;br /&gt;
    //credits, statusbar&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(int battery)&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(temperature[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
  &lt;br /&gt;
  if(c==7)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Set_Text_Mode(0);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
    mylcd.Print_Number_Float(sum[p], 3, xc+60, yc+22, '.', 0, ' ');&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  }&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw) // Convert the readings from the ADC to human readable&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit this loop will calculate it live but the look up table saves clock cycles&lt;br /&gt;
  //Supports Rounding&lt;br /&gt;
  //if( (raw*1.555)-26.0 - (int) ((raw*1.555)-26.0) &amp;gt;= 0.5)&lt;br /&gt;
  //  return (int)((raw*1.555)-25.0);&lt;br /&gt;
  //else&lt;br /&gt;
  //  return (int)((raw*1.555)-26.0);&lt;br /&gt;
  short static const table[256] = &lt;br /&gt;
                     {-26, -24,-23,-21,-20,-18,-17,-15,-14,-12,-10,-9,-7,-6,-4,-3,-1,&lt;br /&gt;
                      0,2,4,5,7,8,10,11,13,14,16,18,19,21,22,24,25,27,28,30,32,33,35,&lt;br /&gt;
                      36,38,39,41,42,44,46,47,49,50,52,53,55,56,58,60,61,63,64,66,67,&lt;br /&gt;
                      69,70,72,74,75,77,78,80,81,83,84,86,88,89,91,92,94,95,97,98,100,&lt;br /&gt;
                      102,103,105,106,108,109,111,112,114,116,117,119,120,122,123,125,&lt;br /&gt;
                      126,128,130,131,133,134,136,137,139,140,142,143,145,147,148,150,&lt;br /&gt;
                      151,153,154,156,157,159,161,162,164,165,167,168,170,171,173,175,&lt;br /&gt;
                      176,178,179,181,182,184,185,187,189,190,192,193,195,196,198,199,&lt;br /&gt;
                      201,203,204,206,207,209,210,212,213,215,217,218,220,221,223,224,&lt;br /&gt;
                      226,227,229,231,232,234,235,237,238,240,241,243,245,246,248,249,&lt;br /&gt;
                      251,252,254,255,257,259,260,262,263,265,266,268,269,271,273,274,&lt;br /&gt;
                      276,277,279,280,282,283,285,287,288,290,291,293,294,296,297,299,&lt;br /&gt;
                      301,302,304,305,307,308,310,311,313,315,316,318,319,321,322,324,&lt;br /&gt;
                      325,327,329,330,332,333,335,336,338,339,341,343,344,346,347,349,&lt;br /&gt;
                      350,352,353,355,357,358,360,361,363,364,366,367,369,371};&lt;br /&gt;
  return (int)table[raw]; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preTransmission() //Put RS485 into transmit mode by bringing the transmit and receive pins high&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 1);&lt;br /&gt;
  digitalWrite(MAX485_DE, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void postTransmission() //Put the RS485 into receive mode by bringing the transmit and receive pins low&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
}&lt;br /&gt;
void getControllerParams() // Hit the controller with a request for information&lt;br /&gt;
{&lt;br /&gt;
uint8_t result;&lt;br /&gt;
&lt;br /&gt;
  // Read 8 registers starting at 0x3100)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readInputRegisters(0x3100, 5);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    PANEL_VOLTS_READ = node.getResponseBuffer(PANEL_VOLTS); //Data slot 0&lt;br /&gt;
    PANEL_AMPS_READ = node.getResponseBuffer(PANEL_AMPS); //Data slot 1&lt;br /&gt;
    BATT_VOLTS_READ = node.getResponseBuffer(BATT_VOLTS); //Data slot 4 (2,3 skipped, not needed)&lt;br /&gt;
  } &lt;br /&gt;
  else { //If there's an error send it to the console&lt;br /&gt;
    Serial.print(&amp;quot;Miss read, ret val:&amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
  //delay(1000);&lt;br /&gt;
&lt;br /&gt;
  // Read 7 registers starting at 0x9003)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readHoldingRegisters(0x9003, 7);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    OVERVOLT_DISC_CURRENT = node.getResponseBuffer(OVERVOLT_DISC);&lt;br /&gt;
    CHARGING_LIMIT_CURRENT = node.getResponseBuffer(CHARGING_LIMIT);&lt;br /&gt;
    OVERVOLT_RECON_CURRENT = node.getResponseBuffer(OVERVOLT_RECON);&lt;br /&gt;
    EQUILIBRIUM_CV_CURRENT = node.getResponseBuffer(EQUILIBRIUM_CV);&lt;br /&gt;
    BOOST_CV_CURRENT = node.getResponseBuffer(BOOST_CV);&lt;br /&gt;
    FLOAT_CV_CURRENT = node.getResponseBuffer(FLOAT_CV);&lt;br /&gt;
    BOOST_RECON_CURRENT = node.getResponseBuffer(BOOST_RECON);&lt;br /&gt;
  } &lt;br /&gt;
  else {&lt;br /&gt;
    Serial.print(&amp;quot;Miss read, ret val:&amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //delay(2000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void windDown() // Quickly bring the controller charge voltage down so the hot cell will kalm&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  OVERVOLT_DISC_SETTO = BATT_VOLTS_READ + 50;&lt;br /&gt;
  CHARGING_LIMIT_SETTO = BATT_VOLTS_READ - 20;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  BOOST_CV_SETTO = BATT_VOLTS_READ - 40;&lt;br /&gt;
  FLOAT_CV_SETTO = BATT_VOLTS_READ - 50;&lt;br /&gt;
  BOOST_RECON_SETTO = BATT_VOLTS_READ - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
}&lt;br /&gt;
void windUp() // Bring the controller charge voltage as close to max as possible&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  unsigned short difference = int((ALARM - hotCellVolt) * 100);&lt;br /&gt;
  unsigned short setvolt = BATT_VOLTS_READ + difference;&lt;br /&gt;
  OVERVOLT_DISC_SETTO = (setvolt + 50);&lt;br /&gt;
  CHARGING_LIMIT_SETTO = setvolt;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = setvolt - 10;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = setvolt - 20;&lt;br /&gt;
  BOOST_CV_SETTO = setvolt - 30;&lt;br /&gt;
  FLOAT_CV_SETTO = setvolt - 40;&lt;br /&gt;
  BOOST_RECON_SETTO = setvolt - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
}&lt;br /&gt;
void updateController() // Send new information to the controller&lt;br /&gt;
{&lt;br /&gt;
  node.clearTransmitBuffer(); //Prepare the buffer with new data, clear and fill&lt;br /&gt;
  node.setTransmitBuffer(0, OVERVOLT_DISC_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(1, CHARGING_LIMIT_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(2, OVERVOLT_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(3, EQUILIBRIUM_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(4, BOOST_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(5, FLOAT_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(6, BOOST_RECON_SETTO);&lt;br /&gt;
  unsigned short result = (node.writeMultipleRegisters(9003,7)); //Yeet!&lt;br /&gt;
  if (result == 0) //Verify&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameters changed sucessfully&amp;quot;);&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Controller parameter change failed, error: &amp;quot;);&lt;br /&gt;
    Serial.println(result);;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=90</id>
		<title>CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=90"/>
		<updated>2020-12-09T05:00:56Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: MODBUS integration partially done but not tested and not yet commented.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
This was developed to test communication to the EPEVER AN Solar controller from the Arduino&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;mcp_can.h&amp;gt;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library http://www.lcdwiki.com/3.5inch_Arduino_Display-UNO&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
#include &amp;lt;ModbusMaster.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS 4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS 8     //Hazardous to modify&lt;br /&gt;
#define REFRESH 1000   //Refresh rate display&lt;br /&gt;
#define ALARM 3.640    //Alarm threshold&lt;br /&gt;
&lt;br /&gt;
//Define the default values for your pack here, value *100, no decimal&lt;br /&gt;
#define def_OVERVOLT_DISC_VAL   2950&lt;br /&gt;
#define def_CHARGING_LIMIT_VAL  2860&lt;br /&gt;
#define def_OVERVOLT_RECON_VAL  2880&lt;br /&gt;
#define def_EQUILIBRIUM_CV_VAL  2830&lt;br /&gt;
#define def_BOOST_CV_VAL        2830&lt;br /&gt;
#define def_FLOAT_CV_VAL        2760        &lt;br /&gt;
#define def_BOOST_RECON_VAL     2640        &lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x1863&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RS485 converter connections&lt;br /&gt;
#define MAX485_DE   49&lt;br /&gt;
#define MAX485_RE   48&lt;br /&gt;
&lt;br /&gt;
// For Epever AN controller MODBUS read&lt;br /&gt;
#define PANEL_VOLTS     0x00&lt;br /&gt;
#define PANEL_AMPS      0x01&lt;br /&gt;
#define PANEL_POWER_L   0x02&lt;br /&gt;
#define PANEL_POWER_H   0x03&lt;br /&gt;
#define BATT_VOLTS      0x04&lt;br /&gt;
#define BATT_AMPS       0x05&lt;br /&gt;
#define BATT_POWER_L    0x06&lt;br /&gt;
#define BATT_POWER_H    0x07&lt;br /&gt;
#define OVERVOLT_DISC   0x00&lt;br /&gt;
#define CHARGING_LIMIT  0x01&lt;br /&gt;
#define OVERVOLT_RECON  0x02&lt;br /&gt;
#define EQUILIBRIUM_CV  0x03&lt;br /&gt;
#define BOOST_CV        0x04&lt;br /&gt;
#define FLOAT_CV        0x05&lt;br /&gt;
#define BOOST_RECON     0x06&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
int temperature[NUMPACKS][NUMCELLS];&lt;br /&gt;
&lt;br /&gt;
//Pack Parameters - you will fill this info in once you find the CAN address of your packs. Only the last two numbers will be relevant&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
unsigned short hotCellVolt = 0;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding the solar controller's set values&lt;br /&gt;
unsigned short OVERVOLT_DISC_CURRENT;&lt;br /&gt;
unsigned short CHARGING_LIMIT_CURRENT;&lt;br /&gt;
unsigned short OVERVOLT_RECON_CURRENT;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_CURRENT;&lt;br /&gt;
unsigned short BOOST_CV_CURRENT;&lt;br /&gt;
unsigned short FLOAT_CV_CURRENT;&lt;br /&gt;
unsigned short BOOST_RECON_CURRENT;&lt;br /&gt;
bool is_Controller_default;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding register values from the controller&lt;br /&gt;
unsigned short PANEL_VOLTS_READ;&lt;br /&gt;
unsigned short PANEL_AMPS_READ;&lt;br /&gt;
unsigned short BATT_VOLTS_READ;&lt;br /&gt;
unsigned short BATT_AMPS_READ;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding values to be sent to the solar controller&lt;br /&gt;
unsigned short OVERVOLT_DISC_SETTO;&lt;br /&gt;
unsigned short CHARGING_LIMIT_SETTO;&lt;br /&gt;
unsigned short OVERVOLT_RECON_SETTO;&lt;br /&gt;
unsigned short EQUILIBRIUM_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_CV_SETTO;&lt;br /&gt;
unsigned short FLOAT_CV_SETTO;&lt;br /&gt;
unsigned short BOOST_RECON_SETTO;&lt;br /&gt;
&lt;br /&gt;
//unsigned char bufA[10];&lt;br /&gt;
//unsigned char buf0[10];&lt;br /&gt;
//unsigned char buf3[10];&lt;br /&gt;
//unsigned char buf5[10];&lt;br /&gt;
//unsigned char buf20[10];&lt;br /&gt;
//unsigned char buf21[10];&lt;br /&gt;
//unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
// instantiate ModbusMaster object&lt;br /&gt;
ModbusMaster node;&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
long st, fn;&lt;br /&gt;
int q;  &lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temperature[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  pinMode(MAX485_RE, OUTPUT);&lt;br /&gt;
  pinMode(MAX485_DE, OUTPUT);&lt;br /&gt;
  // Init in receive mode&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
  &lt;br /&gt;
  // Modbus setup at 115200 baud&lt;br /&gt;
  Serial1.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  // EPEver Device ID 1&lt;br /&gt;
  node.begin(1, Serial1);&lt;br /&gt;
&lt;br /&gt;
  // Callbacks&lt;br /&gt;
  node.preTransmission(preTransmission);&lt;br /&gt;
  node.postTransmission(postTransmission);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);        &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    Serial.print(&amp;quot;p&amp;quot;);//packet received&lt;br /&gt;
&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temperature[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temperature[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temperature[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temperature[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temperature code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temperature code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        //for(int i = 0; i&amp;lt;len; i++) {buf3[i] = buf[i];}&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500) ;//{for(int i = 0; i&amp;lt;len; i++){buf5[i] = buf[i];}}&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00) ;//{for(int i = 0; i&amp;lt;len; i++){bufA[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000) ;//{for(int i = 0; i&amp;lt;len; i++){buf0[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][7] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][6] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][5] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf20[i] = buf[i];} &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][4] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][3] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][2] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf21[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][1] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][0] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf22[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
        //TestTemp();&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        hotCellVolt = 0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          sum[i]=0.0;&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
            sum[i] += voltage[i][j];&lt;br /&gt;
            if (voltage[i][j] &amp;gt; hotCellVolt)&lt;br /&gt;
              hotCellVolt = voltage[i][j];&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)&lt;br /&gt;
            {&lt;br /&gt;
              buzzer=HIGH;&lt;br /&gt;
            }&lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;&lt;br /&gt;
        &lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen(0);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode==0)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blues&lt;br /&gt;
    mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
    mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blacks&lt;br /&gt;
    mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,42 , 150, 191);   //Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,42 , 310, 191);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,234 , 150, 386);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170, 234 , 310, 386);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Lines&lt;br /&gt;
    mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
    mylcd.Draw_Line(11, 62, 149, 62);//Pack 1&lt;br /&gt;
    mylcd.Draw_Line(171, 62, 309, 62);//Pack 2&lt;br /&gt;
    mylcd.Draw_Line(11, 254, 149, 254);//Pack 3&lt;br /&gt;
    mylcd.Draw_Line(171, 254, 309, 254);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Reds &lt;br /&gt;
    mylcd.Set_Draw_color(RED);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,193 , 150, 214);//Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,193, 310, 214);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,384 , 150, 407);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170,384, 310, 407);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Set_Text_Mode(1);&lt;br /&gt;
    mylcd.Set_Text_Size(3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
&lt;br /&gt;
    mylcd.Set_Text_Size(2);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x04    (-)   x20    (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*10);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x06    (-)   x22    (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*22);&lt;br /&gt;
&lt;br /&gt;
    //credits, statusbar&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(int battery)&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(temperature[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
  &lt;br /&gt;
  if(c==7)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Set_Text_Mode(0);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
    mylcd.Print_Number_Float(sum[p], 3, xc+60, yc+22, '.', 0, ' ');&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  }&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw)&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit&lt;br /&gt;
  //Supports Rounding&lt;br /&gt;
  //if( (raw*1.555)-26.0 - (int) ((raw*1.555)-26.0) &amp;gt;= 0.5)&lt;br /&gt;
  //  return (int)((raw*1.555)-25.0);&lt;br /&gt;
  //else&lt;br /&gt;
  //  return (int)((raw*1.555)-26.0);&lt;br /&gt;
  short static const table[256] = &lt;br /&gt;
                     {-26, -24,-23,-21,-20,-18,-17,-15,-14,-12,-10,-9,-7,-6,-4,-3,-1,&lt;br /&gt;
                      0,2,4,5,7,8,10,11,13,14,16,18,19,21,22,24,25,27,28,30,32,33,35,&lt;br /&gt;
                      36,38,39,41,42,44,46,47,49,50,52,53,55,56,58,60,61,63,64,66,67,&lt;br /&gt;
                      69,70,72,74,75,77,78,80,81,83,84,86,88,89,91,92,94,95,97,98,100,&lt;br /&gt;
                      102,103,105,106,108,109,111,112,114,116,117,119,120,122,123,125,&lt;br /&gt;
                      126,128,130,131,133,134,136,137,139,140,142,143,145,147,148,150,&lt;br /&gt;
                      151,153,154,156,157,159,161,162,164,165,167,168,170,171,173,175,&lt;br /&gt;
                      176,178,179,181,182,184,185,187,189,190,192,193,195,196,198,199,&lt;br /&gt;
                      201,203,204,206,207,209,210,212,213,215,217,218,220,221,223,224,&lt;br /&gt;
                      226,227,229,231,232,234,235,237,238,240,241,243,245,246,248,249,&lt;br /&gt;
                      251,252,254,255,257,259,260,262,263,265,266,268,269,271,273,274,&lt;br /&gt;
                      276,277,279,280,282,283,285,287,288,290,291,293,294,296,297,299,&lt;br /&gt;
                      301,302,304,305,307,308,310,311,313,315,316,318,319,321,322,324,&lt;br /&gt;
                      325,327,329,330,332,333,335,336,338,339,341,343,344,346,347,349,&lt;br /&gt;
                      350,352,353,355,357,358,360,361,363,364,366,367,369,371};&lt;br /&gt;
  return (int)table[raw]; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preTransmission()&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 1);&lt;br /&gt;
  digitalWrite(MAX485_DE, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void postTransmission()&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
}&lt;br /&gt;
void getControllerParams()&lt;br /&gt;
{&lt;br /&gt;
uint8_t result;&lt;br /&gt;
&lt;br /&gt;
  // Read 8 registers starting at 0x3100)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readInputRegisters(0x3100, 5);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    PANEL_VOLTS_READ = node.getResponseBuffer(PANEL_VOLTS);&lt;br /&gt;
    PANEL_AMPS_READ = node.getResponseBuffer(PANEL_AMPS);&lt;br /&gt;
    BATT_VOLTS_READ = node.getResponseBuffer(BATT_VOLTS);&lt;br /&gt;
  } &lt;br /&gt;
  else {&lt;br /&gt;
    Serial.print(&amp;quot;Miss read, ret val:&amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
  //delay(1000);&lt;br /&gt;
&lt;br /&gt;
  // Read 7 registers starting at 0x9003)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readHoldingRegisters(0x9003, 7);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    OVERVOLT_DISC_CURRENT = node.getResponseBuffer(OVERVOLT_DISC);&lt;br /&gt;
    CHARGING_LIMIT_CURRENT = node.getResponseBuffer(CHARGING_LIMIT);&lt;br /&gt;
    OVERVOLT_RECON_CURRENT = node.getResponseBuffer(OVERVOLT_RECON);&lt;br /&gt;
    EQUILIBRIUM_CV_CURRENT = node.getResponseBuffer(EQUILIBRIUM_CV);&lt;br /&gt;
    BOOST_CV_CURRENT = node.getResponseBuffer(BOOST_CV);&lt;br /&gt;
    FLOAT_CV_CURRENT = node.getResponseBuffer(FLOAT_CV);&lt;br /&gt;
    BOOST_RECON_CURRENT = node.getResponseBuffer(BOOST_RECON);&lt;br /&gt;
  } &lt;br /&gt;
  else {&lt;br /&gt;
    Serial.print(&amp;quot;Miss read, ret val:&amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //delay(2000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void windDown()&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  OVERVOLT_DISC_SETTO = BATT_VOLTS_READ + 50;&lt;br /&gt;
  CHARGING_LIMIT_SETTO = BATT_VOLTS_READ - 20;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = BATT_VOLTS_READ - 30;&lt;br /&gt;
  BOOST_CV_SETTO = BATT_VOLTS_READ - 40;&lt;br /&gt;
  FLOAT_CV_SETTO = BATT_VOLTS_READ - 50;&lt;br /&gt;
  BOOST_RECON_SETTO = BATT_VOLTS_READ - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
}&lt;br /&gt;
void windUp()&lt;br /&gt;
{&lt;br /&gt;
  getControllerParams();&lt;br /&gt;
  unsigned short difference = int((3.65 - hotCellVolt) * 100);&lt;br /&gt;
  unsigned short setvolt = BATT_VOLTS_READ + difference;&lt;br /&gt;
  OVERVOLT_DISC_SETTO = (setvolt + 50);&lt;br /&gt;
  CHARGING_LIMIT_SETTO = setvolt;&lt;br /&gt;
  OVERVOLT_RECON_SETTO = setvolt - 10;&lt;br /&gt;
  EQUILIBRIUM_CV_SETTO = setvolt - 20;&lt;br /&gt;
  BOOST_CV_SETTO = setvolt - 30;&lt;br /&gt;
  FLOAT_CV_SETTO = setvolt - 40;&lt;br /&gt;
  BOOST_RECON_SETTO = setvolt - 200;&lt;br /&gt;
  updateController();&lt;br /&gt;
}&lt;br /&gt;
void updateController()&lt;br /&gt;
{&lt;br /&gt;
  node.clearTransmitBuffer();&lt;br /&gt;
  node.setTransmitBuffer(0, OVERVOLT_DISC_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(1, CHARGING_LIMIT_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(2, OVERVOLT_RECON_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(3, EQUILIBRIUM_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(4, BOOST_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(5, FLOAT_CV_SETTO);&lt;br /&gt;
  node.setTransmitBuffer(6, BOOST_RECON_SETTO);&lt;br /&gt;
  node.writeMultipleRegisters(9003,7);&lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=87</id>
		<title>CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=87"/>
		<updated>2020-12-09T01:55:05Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: Added stored variables from controller registers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
This was developed to test communication to the EPEVER AN Solar controller from the Arduino&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;mcp_can.h&amp;gt;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library http://www.lcdwiki.com/3.5inch_Arduino_Display-UNO&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
#include &amp;lt;ModbusMaster.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS 4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS 8     //Hazardous to modify&lt;br /&gt;
#define REFRESH 1000   //Refresh rate display&lt;br /&gt;
#define ALARM 3.640    //Alarm threshold&lt;br /&gt;
&lt;br /&gt;
//Define the default values for your pack here, value *100, no decimal&lt;br /&gt;
#define def_OVERVOLT_DISC_VAL   2950&lt;br /&gt;
#define def_CHARGING_LIMIT_VAL  2860&lt;br /&gt;
#define def_OVERVOLT_RECON_VAL  2880&lt;br /&gt;
#define def_EQUILIBRIUM_CV_VAL  2830&lt;br /&gt;
#define def_BOOST_CV_VAL        2830&lt;br /&gt;
#define def_FLOAT_CV_VAL        2760        &lt;br /&gt;
#define def_BOOST_RECON_VAL     2640        &lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x1863&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RS485 converter connections&lt;br /&gt;
#define MAX485_DE   49&lt;br /&gt;
#define MAX485_RE   48&lt;br /&gt;
&lt;br /&gt;
// For Epever AN controller MODBUS read&lt;br /&gt;
#define PANEL_VOLTS     0x00&lt;br /&gt;
#define PANEL_AMPS      0x01&lt;br /&gt;
#define PANEL_POWER_L   0x02&lt;br /&gt;
#define PANEL_POWER_H   0x03&lt;br /&gt;
#define BATT_VOLTS      0x04&lt;br /&gt;
#define BATT_AMPS       0x05&lt;br /&gt;
#define BATT_POWER_L    0x06&lt;br /&gt;
#define BATT_POWER_H    0x07&lt;br /&gt;
#define OVERVOLT_DISC   0x00&lt;br /&gt;
#define CHARGING_LIMIT  0x01&lt;br /&gt;
#define OVERVOLT_RECON  0x02&lt;br /&gt;
#define EQUILIBRIUM_CV  0x03&lt;br /&gt;
#define BOOST_CV        0x04&lt;br /&gt;
#define FLOAT_CV        0x05&lt;br /&gt;
#define BOOST_RECON     0x06&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
int temperature[NUMPACKS][NUMCELLS];&lt;br /&gt;
&lt;br /&gt;
//Pack Parameters - you will fill this info in once you find the CAN address of your packs. Only the last two numbers will be relevant&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding the solar controller's set values&lt;br /&gt;
float OVERVOLT_DISC_CURRENT;&lt;br /&gt;
float CHARGING_LIMIT_CURRENT;&lt;br /&gt;
float OVERVOLT_RECON_CURRENT;&lt;br /&gt;
float EQUILIBRIUM_CV_CURRENT;&lt;br /&gt;
float BOOST_CV_CURRENT;&lt;br /&gt;
float FLOAT_CV_CURRENT;&lt;br /&gt;
float BOOST_RECON_CURRENT;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding register values from the controller&lt;br /&gt;
float PANEL_VOLTS_READ;&lt;br /&gt;
float PANEL_AMPS_READ;&lt;br /&gt;
float BATT_VOLTS_READ;&lt;br /&gt;
float BATT_AMPS_READ;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding values to be sent to the solar controller&lt;br /&gt;
float OVERVOLT_DISC_SETTO;&lt;br /&gt;
float CHARGING_LIMIT_SETTO;&lt;br /&gt;
float OVERVOLT_RECON_SETTO;&lt;br /&gt;
float EQUILIBRIUM_CV_SETTO;&lt;br /&gt;
float BOOST_CV_SETTO;&lt;br /&gt;
float FLOAT_CV_SETTO;&lt;br /&gt;
float BOOST_RECON_SETTO;&lt;br /&gt;
&lt;br /&gt;
//unsigned char bufA[10];&lt;br /&gt;
//unsigned char buf0[10];&lt;br /&gt;
//unsigned char buf3[10];&lt;br /&gt;
//unsigned char buf5[10];&lt;br /&gt;
//unsigned char buf20[10];&lt;br /&gt;
//unsigned char buf21[10];&lt;br /&gt;
//unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
// instantiate ModbusMaster object&lt;br /&gt;
ModbusMaster node;&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
long st, fn;&lt;br /&gt;
int q;  &lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temperature[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  // Modbus setup at 115200 baud&lt;br /&gt;
  Serial1.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  // EPEver Device ID 1&lt;br /&gt;
  node.begin(1, Serial1);&lt;br /&gt;
&lt;br /&gt;
  // Callbacks&lt;br /&gt;
  node.preTransmission(preTransmission);&lt;br /&gt;
  node.postTransmission(postTransmission);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);        &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    Serial.print(&amp;quot;p&amp;quot;);//packet received&lt;br /&gt;
&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temperature[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temperature[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temperature[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temperature[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temperature code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temperature code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        //for(int i = 0; i&amp;lt;len; i++) {buf3[i] = buf[i];}&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500) ;//{for(int i = 0; i&amp;lt;len; i++){buf5[i] = buf[i];}}&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00) ;//{for(int i = 0; i&amp;lt;len; i++){bufA[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000) ;//{for(int i = 0; i&amp;lt;len; i++){buf0[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][7] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][6] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][5] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf20[i] = buf[i];} &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][4] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][3] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][2] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf21[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][1] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][0] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf22[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
        //TestTemp();&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          sum[i]=0.0;&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
            sum[i] += voltage[i][j];&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)  buzzer=HIGH;&lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;&lt;br /&gt;
        &lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen(0);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode==0)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blues&lt;br /&gt;
    mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
    mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blacks&lt;br /&gt;
    mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,42 , 150, 191);   //Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,42 , 310, 191);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,234 , 150, 386);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170, 234 , 310, 386);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Lines&lt;br /&gt;
    mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
    mylcd.Draw_Line(11, 62, 149, 62);//Pack 1&lt;br /&gt;
    mylcd.Draw_Line(171, 62, 309, 62);//Pack 2&lt;br /&gt;
    mylcd.Draw_Line(11, 254, 149, 254);//Pack 3&lt;br /&gt;
    mylcd.Draw_Line(171, 254, 309, 254);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Reds &lt;br /&gt;
    mylcd.Set_Draw_color(RED);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,193 , 150, 214);//Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,193, 310, 214);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,384 , 150, 407);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170,384, 310, 407);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Set_Text_Mode(1);&lt;br /&gt;
    mylcd.Set_Text_Size(3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
&lt;br /&gt;
    mylcd.Set_Text_Size(2);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x04    (-)   x20    (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*10);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x06    (-)   x22    (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*22);&lt;br /&gt;
&lt;br /&gt;
    //credits, statusbar&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(int battery)&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(temperature[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
  &lt;br /&gt;
  if(c==7)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Set_Text_Mode(0);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
    mylcd.Print_Number_Float(sum[p], 3, xc+60, yc+22, '.', 0, ' ');&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  }&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw)&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit&lt;br /&gt;
  //Supports Rounding&lt;br /&gt;
  //if( (raw*1.555)-26.0 - (int) ((raw*1.555)-26.0) &amp;gt;= 0.5)&lt;br /&gt;
  //  return (int)((raw*1.555)-25.0);&lt;br /&gt;
  //else&lt;br /&gt;
  //  return (int)((raw*1.555)-26.0);&lt;br /&gt;
  short static const table[256] = &lt;br /&gt;
                     {-26, -24,-23,-21,-20,-18,-17,-15,-14,-12,-10,-9,-7,-6,-4,-3,-1,&lt;br /&gt;
                      0,2,4,5,7,8,10,11,13,14,16,18,19,21,22,24,25,27,28,30,32,33,35,&lt;br /&gt;
                      36,38,39,41,42,44,46,47,49,50,52,53,55,56,58,60,61,63,64,66,67,&lt;br /&gt;
                      69,70,72,74,75,77,78,80,81,83,84,86,88,89,91,92,94,95,97,98,100,&lt;br /&gt;
                      102,103,105,106,108,109,111,112,114,116,117,119,120,122,123,125,&lt;br /&gt;
                      126,128,130,131,133,134,136,137,139,140,142,143,145,147,148,150,&lt;br /&gt;
                      151,153,154,156,157,159,161,162,164,165,167,168,170,171,173,175,&lt;br /&gt;
                      176,178,179,181,182,184,185,187,189,190,192,193,195,196,198,199,&lt;br /&gt;
                      201,203,204,206,207,209,210,212,213,215,217,218,220,221,223,224,&lt;br /&gt;
                      226,227,229,231,232,234,235,237,238,240,241,243,245,246,248,249,&lt;br /&gt;
                      251,252,254,255,257,259,260,262,263,265,266,268,269,271,273,274,&lt;br /&gt;
                      276,277,279,280,282,283,285,287,288,290,291,293,294,296,297,299,&lt;br /&gt;
                      301,302,304,305,307,308,310,311,313,315,316,318,319,321,322,324,&lt;br /&gt;
                      325,327,329,330,332,333,335,336,338,339,341,343,344,346,347,349,&lt;br /&gt;
                      350,352,353,355,357,358,360,361,363,364,366,367,369,371};&lt;br /&gt;
  return (int)table[raw]; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preTransmission()&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 1);&lt;br /&gt;
  digitalWrite(MAX485_DE, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void postTransmission()&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=Arduino_Projects&amp;diff=86</id>
		<title>Arduino Projects</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=Arduino_Projects&amp;diff=86"/>
		<updated>2020-12-09T01:41:06Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560]]&lt;br /&gt;
&lt;br /&gt;
[[CAN bus battery monitor with 3.5&amp;quot; TFT Touch screen on Arudino MEGA2560]]&lt;br /&gt;
&lt;br /&gt;
[[EPEVER Solar Controller RS485 MODBUS test]]&lt;br /&gt;
&lt;br /&gt;
[[Can bus battery monitor with OLED]]&lt;br /&gt;
&lt;br /&gt;
[[Can bus battery monitor]]&lt;br /&gt;
&lt;br /&gt;
[[OLED Display]]&lt;br /&gt;
&lt;br /&gt;
[[OLED Display SSD1306 i2c 128x64 demo]]&lt;br /&gt;
&lt;br /&gt;
[[LCD demo]]&lt;br /&gt;
&lt;br /&gt;
[[RS485 Master Example]]&lt;br /&gt;
&lt;br /&gt;
[[EPEVER 485]]&lt;br /&gt;
&lt;br /&gt;
[[Vector Clock]]&lt;br /&gt;
&lt;br /&gt;
[[DS1302 RTC Test]]&lt;br /&gt;
&lt;br /&gt;
[[QR Code generation with 3.5&amp;quot; TFT Touch screen on Arudino MEGA2560]]&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=File:Mcp2515_lib.tar.gz&amp;diff=85</id>
		<title>File:Mcp2515 lib.tar.gz</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=File:Mcp2515_lib.tar.gz&amp;diff=85"/>
		<updated>2020-12-09T01:40:40Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: MCP2515 library used in BYD BMS project&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
MCP2515 library used in BYD BMS project&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=Arduino_Projects&amp;diff=84</id>
		<title>Arduino Projects</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=Arduino_Projects&amp;diff=84"/>
		<updated>2020-12-09T01:37:45Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560]]&lt;br /&gt;
&lt;br /&gt;
[[CAN bus battery monitor with 3.5&amp;quot; TFT Touch screen on Arudino MEGA2560]]&lt;br /&gt;
&lt;br /&gt;
[[EPEVER Solar Controller RS485 MODBUS test]]&lt;br /&gt;
&lt;br /&gt;
[[Can bus battery monitor with OLED]]&lt;br /&gt;
&lt;br /&gt;
[[Can bus battery monitor]]&lt;br /&gt;
&lt;br /&gt;
[[OLED Display]]&lt;br /&gt;
&lt;br /&gt;
[[OLED Display SSD1306 i2c 128x64 demo]]&lt;br /&gt;
&lt;br /&gt;
[[LCD demo]]&lt;br /&gt;
&lt;br /&gt;
[[RS485 Master Example]]&lt;br /&gt;
&lt;br /&gt;
[[EPEVER 485]]&lt;br /&gt;
&lt;br /&gt;
[[Vector Clock]]&lt;br /&gt;
&lt;br /&gt;
[[DS1302 RTC Test]]&lt;br /&gt;
&lt;br /&gt;
[[QR Code generation with 3.5&amp;quot; TFT Touch screen on Arudino MEGA2560]]&lt;br /&gt;
&lt;br /&gt;
[[MCP2515_master library]]&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=83</id>
		<title>CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=83"/>
		<updated>2020-12-09T01:04:21Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: Added preTransmission and postTransmission loops&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
This was developed to test communication to the EPEVER AN Solar controller from the Arduino&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;quot;mcp_can.h&amp;quot;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library http://www.lcdwiki.com/3.5inch_Arduino_Display-UNO&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
#include &amp;lt;ModbusMaster.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS 4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS 8     //Hazardous to modify&lt;br /&gt;
#define REFRESH 1000   //Refresh rate display&lt;br /&gt;
#define ALARM 3.640    //Alarm threshold&lt;br /&gt;
&lt;br /&gt;
//Define the default values for your pack here, value *100, no decimal&lt;br /&gt;
#define def_OVERVOLT_DISC_VAL   2950&lt;br /&gt;
#define def_CHARGING_LIMIT_VAL  2860&lt;br /&gt;
#define def_OVERVOLT_DISC_VAL   2900&lt;br /&gt;
#define def_OVERVOLT_RECON_VAL  2880&lt;br /&gt;
#define def_EQUILIBRIUM_CV_VAL  2830&lt;br /&gt;
#define def_BOOST_CV_VAL        2830&lt;br /&gt;
#define def_FLOAT_CV_VAL        2760        &lt;br /&gt;
#define def_BOOST_RECON_VAL     2640        &lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x1863&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RS485 converter connections&lt;br /&gt;
#define MAX485_DE   49&lt;br /&gt;
#define MAX485_RE   48&lt;br /&gt;
&lt;br /&gt;
// For Epever AN controller MODBUS read&lt;br /&gt;
#define PANEL_VOLTS     0x00&lt;br /&gt;
#define PANEL_AMPS      0x01&lt;br /&gt;
#define PANEL_POWER_L   0x02&lt;br /&gt;
#define PANEL_POWER_H   0x03&lt;br /&gt;
#define BATT_VOLTS      0x04&lt;br /&gt;
#define BATT_AMPS       0x05&lt;br /&gt;
#define BATT_POWER_L    0x06&lt;br /&gt;
#define BATT_POWER_H    0x07&lt;br /&gt;
#define OVERVOLT_DISC   0x00&lt;br /&gt;
#define CHARGING_LIMIT  0x01&lt;br /&gt;
#define OVERVOLT_RECON  0x02&lt;br /&gt;
#define EQUILIBRIUM_CV  0x03&lt;br /&gt;
#define BOOST_CV        0x04&lt;br /&gt;
#define FLOAT_CV        0x05&lt;br /&gt;
#define BOOST_RECON     0x06&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
int temperature[NUMPACKS][NUMCELLS];&lt;br /&gt;
&lt;br /&gt;
//Pack Parameters - you will fill this info in once you find the CAN address of your packs. Only the last two numbers will be relevant&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding the solar controller's set values&lt;br /&gt;
float OVERVOLT_DISC_CURRENT;&lt;br /&gt;
float CHARGING_LIMIT_CURRENT;&lt;br /&gt;
float OVERVOLT_RECON_CURRENT;&lt;br /&gt;
float EQUILIBRIUM_CV_CURRENT;&lt;br /&gt;
float BOOST_CV_CURRENT;&lt;br /&gt;
float FLOAT_CV_CURRENT;&lt;br /&gt;
float BOOST_RECON_CURRENT;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding values to be sent to the solar controller&lt;br /&gt;
float OVERVOLT_DISC_SETTO;&lt;br /&gt;
float CHARGING_LIMIT_SETTO;&lt;br /&gt;
float OVERVOLT_RECON_SETTO;&lt;br /&gt;
float EQUILIBRIUM_CV_SETTO;&lt;br /&gt;
float BOOST_CV_SETTO;&lt;br /&gt;
float FLOAT_CV_SETTO;&lt;br /&gt;
float BOOST_RECON_SETTO;&lt;br /&gt;
&lt;br /&gt;
//unsigned char bufA[10];&lt;br /&gt;
//unsigned char buf0[10];&lt;br /&gt;
//unsigned char buf3[10];&lt;br /&gt;
//unsigned char buf5[10];&lt;br /&gt;
//unsigned char buf20[10];&lt;br /&gt;
//unsigned char buf21[10];&lt;br /&gt;
//unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
// instantiate ModbusMaster object&lt;br /&gt;
ModbusMaster node;&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
long st, fn;&lt;br /&gt;
int q;  &lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temperature[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  // Modbus setup at 115200 baud&lt;br /&gt;
  Serial1.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  // EPEver Device ID 1&lt;br /&gt;
  node.begin(1, Serial1);&lt;br /&gt;
&lt;br /&gt;
  // Callbacks&lt;br /&gt;
  node.preTransmission(preTransmission);&lt;br /&gt;
  node.postTransmission(postTransmission);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);        &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    Serial.print(&amp;quot;p&amp;quot;);//packet received&lt;br /&gt;
&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temperature[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temperature[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temperature[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temperature[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temperature code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temperature code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        //for(int i = 0; i&amp;lt;len; i++) {buf3[i] = buf[i];}&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500) ;//{for(int i = 0; i&amp;lt;len; i++){buf5[i] = buf[i];}}&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00) ;//{for(int i = 0; i&amp;lt;len; i++){bufA[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000) ;//{for(int i = 0; i&amp;lt;len; i++){buf0[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][7] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][6] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][5] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf20[i] = buf[i];} &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][4] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][3] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][2] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf21[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][1] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][0] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf22[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
        //TestTemp();&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          sum[i]=0.0;&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
            sum[i] += voltage[i][j];&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)  buzzer=HIGH;&lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;&lt;br /&gt;
        &lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen(0);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode==0)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blues&lt;br /&gt;
    mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
    mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blacks&lt;br /&gt;
    mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,42 , 150, 191);   //Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,42 , 310, 191);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,234 , 150, 386);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170, 234 , 310, 386);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Lines&lt;br /&gt;
    mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
    mylcd.Draw_Line(11, 62, 149, 62);//Pack 1&lt;br /&gt;
    mylcd.Draw_Line(171, 62, 309, 62);//Pack 2&lt;br /&gt;
    mylcd.Draw_Line(11, 254, 149, 254);//Pack 3&lt;br /&gt;
    mylcd.Draw_Line(171, 254, 309, 254);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Reds &lt;br /&gt;
    mylcd.Set_Draw_color(RED);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,193 , 150, 214);//Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,193, 310, 214);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,384 , 150, 407);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170,384, 310, 407);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Set_Text_Mode(1);&lt;br /&gt;
    mylcd.Set_Text_Size(3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
&lt;br /&gt;
    mylcd.Set_Text_Size(2);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x04    (-)   x20    (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*10);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x06    (-)   x22    (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*22);&lt;br /&gt;
&lt;br /&gt;
    //credits, statusbar&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(int battery)&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(temperature[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
  &lt;br /&gt;
  if(c==7)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Set_Text_Mode(0);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
    mylcd.Print_Number_Float(sum[p], 3, xc+60, yc+22, '.', 0, ' ');&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  }&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw)&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit&lt;br /&gt;
  //Supports Rounding&lt;br /&gt;
  //if( (raw*1.555)-26.0 - (int) ((raw*1.555)-26.0) &amp;gt;= 0.5)&lt;br /&gt;
  //  return (int)((raw*1.555)-25.0);&lt;br /&gt;
  //else&lt;br /&gt;
  //  return (int)((raw*1.555)-26.0);&lt;br /&gt;
  short static const table[256] = &lt;br /&gt;
                     {-26, -24,-23,-21,-20,-18,-17,-15,-14,-12,-10,-9,-7,-6,-4,-3,-1,&lt;br /&gt;
                      0,2,4,5,7,8,10,11,13,14,16,18,19,21,22,24,25,27,28,30,32,33,35,&lt;br /&gt;
                      36,38,39,41,42,44,46,47,49,50,52,53,55,56,58,60,61,63,64,66,67,&lt;br /&gt;
                      69,70,72,74,75,77,78,80,81,83,84,86,88,89,91,92,94,95,97,98,100,&lt;br /&gt;
                      102,103,105,106,108,109,111,112,114,116,117,119,120,122,123,125,&lt;br /&gt;
                      126,128,130,131,133,134,136,137,139,140,142,143,145,147,148,150,&lt;br /&gt;
                      151,153,154,156,157,159,161,162,164,165,167,168,170,171,173,175,&lt;br /&gt;
                      176,178,179,181,182,184,185,187,189,190,192,193,195,196,198,199,&lt;br /&gt;
                      201,203,204,206,207,209,210,212,213,215,217,218,220,221,223,224,&lt;br /&gt;
                      226,227,229,231,232,234,235,237,238,240,241,243,245,246,248,249,&lt;br /&gt;
                      251,252,254,255,257,259,260,262,263,265,266,268,269,271,273,274,&lt;br /&gt;
                      276,277,279,280,282,283,285,287,288,290,291,293,294,296,297,299,&lt;br /&gt;
                      301,302,304,305,307,308,310,311,313,315,316,318,319,321,322,324,&lt;br /&gt;
                      325,327,329,330,332,333,335,336,338,339,341,343,344,346,347,349,&lt;br /&gt;
                      350,352,353,355,357,358,360,361,363,364,366,367,369,371};&lt;br /&gt;
  return (int)table[raw]; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preTransmission()&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 1);&lt;br /&gt;
  digitalWrite(MAX485_DE, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void postTransmission()&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=82</id>
		<title>CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_Battery_Monitor_with_Epever_Controller_Integration_%2B_3.5TFT_Mega2560&amp;diff=82"/>
		<updated>2020-12-09T00:57:24Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: First upload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
This was developed to test communication to the EPEVER AN Solar controller from the Arduino&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;quot;mcp_can.h&amp;quot;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library http://www.lcdwiki.com/3.5inch_Arduino_Display-UNO&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
#include &amp;lt;ModbusMaster.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS 4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS 8     //Hazardous to modify&lt;br /&gt;
#define REFRESH 1000   //Refresh rate display&lt;br /&gt;
#define ALARM 3.640    //Alarm threshold&lt;br /&gt;
&lt;br /&gt;
//Define the default values for your pack here, value *100, no decimal&lt;br /&gt;
#define def_OVERVOLT_DISC_VAL   2950&lt;br /&gt;
#define def_CHARGING_LIMIT_VAL  2860&lt;br /&gt;
#define def_OVERVOLT_DISC_VAL   2900&lt;br /&gt;
#define def_OVERVOLT_RECON_VAL  2880&lt;br /&gt;
#define def_EQUILIBRIUM_CV_VAL  2830&lt;br /&gt;
#define def_BOOST_CV_VAL        2830&lt;br /&gt;
#define def_FLOAT_CV_VAL        2760        &lt;br /&gt;
#define def_BOOST_RECON_VAL     2640        &lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x1863&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RS485 converter connections&lt;br /&gt;
#define MAX485_DE   49&lt;br /&gt;
#define MAX485_RE   48&lt;br /&gt;
&lt;br /&gt;
// For Epever AN controller MODBUS read&lt;br /&gt;
#define PANEL_VOLTS     0x00&lt;br /&gt;
#define PANEL_AMPS      0x01&lt;br /&gt;
#define PANEL_POWER_L   0x02&lt;br /&gt;
#define PANEL_POWER_H   0x03&lt;br /&gt;
#define BATT_VOLTS      0x04&lt;br /&gt;
#define BATT_AMPS       0x05&lt;br /&gt;
#define BATT_POWER_L    0x06&lt;br /&gt;
#define BATT_POWER_H    0x07&lt;br /&gt;
#define OVERVOLT_DISC   0x00&lt;br /&gt;
#define CHARGING_LIMIT  0x01&lt;br /&gt;
#define OVERVOLT_RECON  0x02&lt;br /&gt;
#define EQUILIBRIUM_CV  0x03&lt;br /&gt;
#define BOOST_CV        0x04&lt;br /&gt;
#define FLOAT_CV        0x05&lt;br /&gt;
#define BOOST_RECON     0x06&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
int temperature[NUMPACKS][NUMCELLS];&lt;br /&gt;
&lt;br /&gt;
//Pack Parameters - you will fill this info in once you find the CAN address of your packs. Only the last two numbers will be relevant&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding the solar controller's set values&lt;br /&gt;
float OVERVOLT_DISC_CURRENT;&lt;br /&gt;
float CHARGING_LIMIT_CURRENT;&lt;br /&gt;
float OVERVOLT_RECON_CURRENT;&lt;br /&gt;
float EQUILIBRIUM_CV_CURRENT;&lt;br /&gt;
float BOOST_CV_CURRENT;&lt;br /&gt;
float FLOAT_CV_CURRENT;&lt;br /&gt;
float BOOST_RECON_CURRENT;&lt;br /&gt;
&lt;br /&gt;
//Variables for holding values to be sent to the solar controller&lt;br /&gt;
float OVERVOLT_DISC_SETTO;&lt;br /&gt;
float CHARGING_LIMIT_SETTO;&lt;br /&gt;
float OVERVOLT_RECON_SETTO;&lt;br /&gt;
float EQUILIBRIUM_CV_SETTO;&lt;br /&gt;
float BOOST_CV_SETTO;&lt;br /&gt;
float FLOAT_CV_SETTO;&lt;br /&gt;
float BOOST_RECON_SETTO;&lt;br /&gt;
&lt;br /&gt;
//unsigned char bufA[10];&lt;br /&gt;
//unsigned char buf0[10];&lt;br /&gt;
//unsigned char buf3[10];&lt;br /&gt;
//unsigned char buf5[10];&lt;br /&gt;
//unsigned char buf20[10];&lt;br /&gt;
//unsigned char buf21[10];&lt;br /&gt;
//unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
// instantiate ModbusMaster object&lt;br /&gt;
ModbusMaster node;&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
long st, fn;&lt;br /&gt;
int q;  &lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temperature[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  // Modbus setup at 115200 baud&lt;br /&gt;
  Serial1.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  // EPEver Device ID 1&lt;br /&gt;
  node.begin(1, Serial1);&lt;br /&gt;
&lt;br /&gt;
  // Callbacks&lt;br /&gt;
  node.preTransmission(preTransmission);&lt;br /&gt;
  node.postTransmission(postTransmission);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);        &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    Serial.print(&amp;quot;p&amp;quot;);//packet received&lt;br /&gt;
&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temperature[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temperature[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temperature[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temperature[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temperature code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temperature code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        //for(int i = 0; i&amp;lt;len; i++) {buf3[i] = buf[i];}&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500) ;//{for(int i = 0; i&amp;lt;len; i++){buf5[i] = buf[i];}}&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00) ;//{for(int i = 0; i&amp;lt;len; i++){bufA[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000) ;//{for(int i = 0; i&amp;lt;len; i++){buf0[i] = buf[i];}}&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][7] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][6] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][5] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf20[i] = buf[i];} &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][4] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][3] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          voltage[slot][2] = (buf[6] * 256 + buf[5]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf21[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          voltage[slot][1] = (buf[2] * 256 + buf[1]) / 1000.0;&lt;br /&gt;
          voltage[slot][0] = (buf[4] * 256 + buf[3]) / 1000.0;&lt;br /&gt;
          //for(int i = 0; i&amp;lt;len; i++){buf22[i] = buf[i];}&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
        //TestTemp();&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          sum[i]=0.0;&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
            sum[i] += voltage[i][j];&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)  buzzer=HIGH;&lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;&lt;br /&gt;
        &lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen(0);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode==0)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blues&lt;br /&gt;
    mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
    mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
&lt;br /&gt;
    //Draw Blacks&lt;br /&gt;
    mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,42 , 150, 191);   //Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,42 , 310, 191);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,234 , 150, 386);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170, 234 , 310, 386);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Lines&lt;br /&gt;
    mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
    mylcd.Draw_Line(11, 62, 149, 62);//Pack 1&lt;br /&gt;
    mylcd.Draw_Line(171, 62, 309, 62);//Pack 2&lt;br /&gt;
    mylcd.Draw_Line(11, 254, 149, 254);//Pack 3&lt;br /&gt;
    mylcd.Draw_Line(171, 254, 309, 254);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    //Draw Reds &lt;br /&gt;
    mylcd.Set_Draw_color(RED);&lt;br /&gt;
    mylcd.Fill_Rectangle(10,193 , 150, 214);//Pack 1&lt;br /&gt;
    mylcd.Fill_Rectangle(170,193, 310, 214);//Pack 2&lt;br /&gt;
    mylcd.Fill_Rectangle(10,384 , 150, 407);//Pack 3&lt;br /&gt;
    mylcd.Fill_Rectangle(170,384, 310, 407);//Pack 4&lt;br /&gt;
&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Set_Text_Mode(1);&lt;br /&gt;
    mylcd.Set_Text_Size(3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
&lt;br /&gt;
    mylcd.Set_Text_Size(2);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x04    (-)   x20    (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*10);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;  x06    (-)   x22    (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
    mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*22);&lt;br /&gt;
&lt;br /&gt;
    //credits, statusbar&lt;br /&gt;
    mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
    mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(int battery)&lt;br /&gt;
{&lt;br /&gt;
  &lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(temperature[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
  &lt;br /&gt;
  if(c==7)&lt;br /&gt;
  {&lt;br /&gt;
    mylcd.Set_Text_Mode(0);&lt;br /&gt;
    mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
    mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
    mylcd.Print_Number_Float(sum[p], 3, xc+60, yc+22, '.', 0, ' ');&lt;br /&gt;
    mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  }&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw)&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit&lt;br /&gt;
  //Supports Rounding&lt;br /&gt;
  //if( (raw*1.555)-26.0 - (int) ((raw*1.555)-26.0) &amp;gt;= 0.5)&lt;br /&gt;
  //  return (int)((raw*1.555)-25.0);&lt;br /&gt;
  //else&lt;br /&gt;
  //  return (int)((raw*1.555)-26.0);&lt;br /&gt;
  short static const table[256] = &lt;br /&gt;
                     {-26, -24,-23,-21,-20,-18,-17,-15,-14,-12,-10,-9,-7,-6,-4,-3,-1,&lt;br /&gt;
                      0,2,4,5,7,8,10,11,13,14,16,18,19,21,22,24,25,27,28,30,32,33,35,&lt;br /&gt;
                      36,38,39,41,42,44,46,47,49,50,52,53,55,56,58,60,61,63,64,66,67,&lt;br /&gt;
                      69,70,72,74,75,77,78,80,81,83,84,86,88,89,91,92,94,95,97,98,100,&lt;br /&gt;
                      102,103,105,106,108,109,111,112,114,116,117,119,120,122,123,125,&lt;br /&gt;
                      126,128,130,131,133,134,136,137,139,140,142,143,145,147,148,150,&lt;br /&gt;
                      151,153,154,156,157,159,161,162,164,165,167,168,170,171,173,175,&lt;br /&gt;
                      176,178,179,181,182,184,185,187,189,190,192,193,195,196,198,199,&lt;br /&gt;
                      201,203,204,206,207,209,210,212,213,215,217,218,220,221,223,224,&lt;br /&gt;
                      226,227,229,231,232,234,235,237,238,240,241,243,245,246,248,249,&lt;br /&gt;
                      251,252,254,255,257,259,260,262,263,265,266,268,269,271,273,274,&lt;br /&gt;
                      276,277,279,280,282,283,285,287,288,290,291,293,294,296,297,299,&lt;br /&gt;
                      301,302,304,305,307,308,310,311,313,315,316,318,319,321,322,324,&lt;br /&gt;
                      325,327,329,330,332,333,335,336,338,339,341,343,344,346,347,349,&lt;br /&gt;
                      350,352,353,355,357,358,360,361,363,364,366,367,369,371};&lt;br /&gt;
  return (int)table[raw]; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=Arduino_Projects&amp;diff=81</id>
		<title>Arduino Projects</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=Arduino_Projects&amp;diff=81"/>
		<updated>2020-12-09T00:56:23Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: Added new section for Epever integration&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[CAN Battery Monitor with Epever Controller Integration + 3.5TFT Mega2560]]&lt;br /&gt;
&lt;br /&gt;
[[CAN bus battery monitor with 3.5&amp;quot; TFT Touch screen on Arudino MEGA2560]]&lt;br /&gt;
&lt;br /&gt;
[[EPEVER Solar Controller RS485 MODBUS test]]&lt;br /&gt;
&lt;br /&gt;
[[Can bus battery monitor with OLED]]&lt;br /&gt;
&lt;br /&gt;
[[Can bus battery monitor]]&lt;br /&gt;
&lt;br /&gt;
[[OLED Display]]&lt;br /&gt;
&lt;br /&gt;
[[OLED Display SSD1306 i2c 128x64 demo]]&lt;br /&gt;
&lt;br /&gt;
[[LCD demo]]&lt;br /&gt;
&lt;br /&gt;
[[RS485 Master Example]]&lt;br /&gt;
&lt;br /&gt;
[[EPEVER 485]]&lt;br /&gt;
&lt;br /&gt;
[[Vector Clock]]&lt;br /&gt;
&lt;br /&gt;
[[DS1302 RTC Test]]&lt;br /&gt;
&lt;br /&gt;
[[QR Code generation with 3.5&amp;quot; TFT Touch screen on Arudino MEGA2560]]&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=EPEVER_Solar_Controller_RS485_MODBUS_test&amp;diff=80</id>
		<title>EPEVER Solar Controller RS485 MODBUS test</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=EPEVER_Solar_Controller_RS485_MODBUS_test&amp;diff=80"/>
		<updated>2020-12-08T23:55:02Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: First Upload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
This was developed to test communication to the EPEVER AN Solar controller from the Arduino&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
//Power is not currently working for battery or panel&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;ModbusMaster.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define MAX485_DE   49&lt;br /&gt;
#define MAX485_RE   48&lt;br /&gt;
&lt;br /&gt;
#define PANEL_VOLTS     0x00&lt;br /&gt;
#define PANEL_AMPS      0x01&lt;br /&gt;
#define PANEL_POWER_L   0x02&lt;br /&gt;
#define PANEL_POWER_H   0x03&lt;br /&gt;
#define BATT_VOLTS      0x04&lt;br /&gt;
#define BATT_AMPS       0x05&lt;br /&gt;
#define BATT_POWER_L    0x06&lt;br /&gt;
#define BATT_POWER_H    0x07&lt;br /&gt;
#define OVERVOLT_DISC   0x00&lt;br /&gt;
#define CHARGING_LIMIT  0x01&lt;br /&gt;
#define OVERVOLT_RECON  0x02&lt;br /&gt;
#define EQUILIBRIUM_CV  0x03&lt;br /&gt;
#define BOOST_CV        0x04&lt;br /&gt;
#define FLOAT_CV        0x05&lt;br /&gt;
#define BOOST_RECON     0x06&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// instantiate ModbusMaster object&lt;br /&gt;
ModbusMaster node;&lt;br /&gt;
&lt;br /&gt;
//#include &amp;lt;SoftwareSerial.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//SoftwareSerial mySerial(10, 11); // RX, TX&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  while (!Serial) {&lt;br /&gt;
    ;&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;Moooooo!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  pinMode(MAX485_RE, OUTPUT);&lt;br /&gt;
  pinMode(MAX485_DE, OUTPUT);&lt;br /&gt;
  // Init in receive mode&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
&lt;br /&gt;
  // Modbus at 115200 baud&lt;br /&gt;
  Serial1.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  // EPEver Device ID 1&lt;br /&gt;
  node.begin(1, Serial1);&lt;br /&gt;
&lt;br /&gt;
  // Callbacks&lt;br /&gt;
  node.preTransmission(preTransmission);&lt;br /&gt;
  node.postTransmission(postTransmission);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  uint8_t result;&lt;br /&gt;
&lt;br /&gt;
  // Read 8 registers starting at 0x3100)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readInputRegisters(0x3100, 8);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;VPanel: &amp;quot;);&lt;br /&gt;
    Serial.println(node.getResponseBuffer(PANEL_VOLTS)/100.0f);&lt;br /&gt;
    Serial.print(&amp;quot;IPanel: &amp;quot;);&lt;br /&gt;
    Serial.println(node.getResponseBuffer(PANEL_AMPS)/100.0f);&lt;br /&gt;
    Serial.print(&amp;quot;PPanel: &amp;quot;);&lt;br /&gt;
    Serial.println((node.getResponseBuffer(PANEL_POWER_L) +&lt;br /&gt;
                    node.getResponseBuffer(PANEL_POWER_H) &amp;lt;&amp;lt; 16)/100.0f);&lt;br /&gt;
   &lt;br /&gt;
    Serial.print(&amp;quot;VBatt: &amp;quot;);&lt;br /&gt;
    Serial.println(node.getResponseBuffer(BATT_VOLTS)/100.0f);&lt;br /&gt;
    Serial.print(&amp;quot;Ibatt: &amp;quot;);&lt;br /&gt;
    Serial.println(node.getResponseBuffer(BATT_AMPS)/100.0f);&lt;br /&gt;
    Serial.print(&amp;quot;PBatt: &amp;quot;);&lt;br /&gt;
    Serial.println((node.getResponseBuffer(BATT_POWER_L) +&lt;br /&gt;
                    node.getResponseBuffer(BATT_POWER_H) &amp;lt;&amp;lt; 16)/100.0f);                   &lt;br /&gt;
    Serial.println();&lt;br /&gt;
    Serial.println();&lt;br /&gt;
  } else {&lt;br /&gt;
    Serial.print(&amp;quot;Miss read, ret val:&amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
  //delay(1000);&lt;br /&gt;
&lt;br /&gt;
  // Read 6 registers starting at 0x9003)&lt;br /&gt;
  node.clearResponseBuffer();&lt;br /&gt;
  result = node.readHoldingRegisters(0x9003, 7);&lt;br /&gt;
&lt;br /&gt;
  if (result == node.ku8MBSuccess)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Overvolt Disconnect Voltage: &amp;quot;);&lt;br /&gt;
    Serial.println(node.getResponseBuffer(OVERVOLT_DISC)/100.0f);&lt;br /&gt;
    Serial.print(&amp;quot;Charging Limit Voltage: &amp;quot;);&lt;br /&gt;
    Serial.println(node.getResponseBuffer(CHARGING_LIMIT)/100.0f);&lt;br /&gt;
    Serial.print(&amp;quot;Overvolt Disconnect Voltage: &amp;quot;);&lt;br /&gt;
    Serial.println(node.getResponseBuffer(OVERVOLT_DISC)/100.0f);&lt;br /&gt;
    Serial.print(&amp;quot;Overvolt Reconnect Voltage: &amp;quot;);&lt;br /&gt;
    Serial.println(node.getResponseBuffer(OVERVOLT_RECON)/100.0f);&lt;br /&gt;
    Serial.print(&amp;quot;Equilibrium Charge Voltage: &amp;quot;);&lt;br /&gt;
    Serial.println(node.getResponseBuffer(EQUILIBRIUM_CV)/100.0f);&lt;br /&gt;
    Serial.print(&amp;quot;Boost Charging Voltage:  &amp;quot;);&lt;br /&gt;
    Serial.println(node.getResponseBuffer(BOOST_CV)/100.0f);&lt;br /&gt;
    Serial.print(&amp;quot;Float Charging Voltage: &amp;quot;);&lt;br /&gt;
    Serial.println(node.getResponseBuffer(FLOAT_CV)/100.0f);&lt;br /&gt;
    Serial.print(&amp;quot;Boost Reconnect Voltage: &amp;quot;);&lt;br /&gt;
    Serial.println(node.getResponseBuffer(BOOST_RECON)/100.0f);&lt;br /&gt;
                  &lt;br /&gt;
    Serial.println();&lt;br /&gt;
    Serial.println();&lt;br /&gt;
  } else {&lt;br /&gt;
    Serial.print(&amp;quot;Miss read, ret val:&amp;quot;);&lt;br /&gt;
    Serial.println(result);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  delay(2000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preTransmission()&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 1);&lt;br /&gt;
  digitalWrite(MAX485_DE, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void postTransmission()&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(MAX485_RE, 0);&lt;br /&gt;
  digitalWrite(MAX485_DE, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=Arduino_Projects&amp;diff=79</id>
		<title>Arduino Projects</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=Arduino_Projects&amp;diff=79"/>
		<updated>2020-12-08T23:52:28Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: Re-arrange and add Epever RS485 test&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[CAN bus battery monitor with 3.5&amp;quot; TFT Touch screen on Arudino MEGA2560]]&lt;br /&gt;
&lt;br /&gt;
[[EPEVER Solar Controller RS485 MODBUS test]]&lt;br /&gt;
&lt;br /&gt;
[[Can bus battery monitor with OLED]]&lt;br /&gt;
&lt;br /&gt;
[[Can bus battery monitor]]&lt;br /&gt;
&lt;br /&gt;
[[OLED Display]]&lt;br /&gt;
&lt;br /&gt;
[[OLED Display SSD1306 i2c 128x64 demo]]&lt;br /&gt;
&lt;br /&gt;
[[LCD demo]]&lt;br /&gt;
&lt;br /&gt;
[[RS485 Master Example]]&lt;br /&gt;
&lt;br /&gt;
[[EPEVER 485]]&lt;br /&gt;
&lt;br /&gt;
[[Vector Clock]]&lt;br /&gt;
&lt;br /&gt;
[[DS1302 RTC Test]]&lt;br /&gt;
&lt;br /&gt;
[[QR Code generation with 3.5&amp;quot; TFT Touch screen on Arudino MEGA2560]]&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=EPEVER_485&amp;diff=72</id>
		<title>EPEVER 485</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=EPEVER_485&amp;diff=72"/>
		<updated>2020-11-19T06:05:40Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
Issues 485 request and display result&lt;br /&gt;
==Notes==&lt;br /&gt;
===9000-9100 Registers===&lt;br /&gt;
&lt;br /&gt;
0xFFFF9000 : 0x00&lt;br /&gt;
0xFFFF9001 : 0x70&lt;br /&gt;
0xFFFF9002 : 0x00&lt;br /&gt;
0xFFFF9003 : 0x86&lt;br /&gt;
0xFFFF9004 : 0x68&lt;br /&gt;
0xFFFF9005 : 0x5E&lt;br /&gt;
0xFFFF9006 : 0x54&lt;br /&gt;
0xFFFF9007 : 0x54&lt;br /&gt;
0xFFFF9008 : 0xC8&lt;br /&gt;
0xFFFF9009 : 0x50&lt;br /&gt;
0xFFFF900A : 0x00&lt;br /&gt;
0xFFFF900B : 0x00&lt;br /&gt;
0xFFFF900C : 0x60&lt;br /&gt;
0xFFFF900D : 0xAC&lt;br /&gt;
0xFFFF900E : 0x48&lt;br /&gt;
0xFFFF900F : 0x00&lt;br /&gt;
0xFFFF9010 : 0x64&lt;br /&gt;
0xFFFF9011 : 0x00&lt;br /&gt;
0xFFFF9012 : Error 0x02&lt;br /&gt;
0xFFFF9013 : 0x27&lt;br /&gt;
0xFFFF9014 : 0x15&lt;br /&gt;
0xFFFF9015 : 0x0B&lt;br /&gt;
0xFFFF9016 : 0x1E&lt;br /&gt;
0xFFFF9017 : 0x4C&lt;br /&gt;
0xFFFF9018 : 0x00&lt;br /&gt;
0xFFFF9019 : 0x1C&lt;br /&gt;
0xFFFF901A : 0x40&lt;br /&gt;
0xFFFF901B : 0x34&lt;br /&gt;
0xFFFF901C : 0x4C&lt;br /&gt;
0xFFFF901D : 0x02&lt;br /&gt;
0xFFFF901E : 0xE8&lt;br /&gt;
0xFFFF901F : 0x0A&lt;br /&gt;
0xFFFF9020 : 0xB0&lt;br /&gt;
0xFFFF9021 : 0x0A&lt;br /&gt;
0xFFFF9022 : Error 0x02&lt;br /&gt;
0xFFFF9023 : Error 0x02&lt;br /&gt;
0xFFFF9024 : Error 0x02&lt;br /&gt;
0xFFFF9025 : Error 0x02&lt;br /&gt;
0xFFFF9026 : Error 0x02&lt;br /&gt;
0xFFFF9027 : Error 0x02&lt;br /&gt;
0xFFFF9028 : Error 0x02&lt;br /&gt;
0xFFFF9029 : Error 0x02&lt;br /&gt;
0xFFFF902A : Error 0x02&lt;br /&gt;
0xFFFF902B : Error 0x02&lt;br /&gt;
0xFFFF902C : Error 0x02&lt;br /&gt;
0xFFFF902D : Error 0x02&lt;br /&gt;
0xFFFF902E : Error 0x02&lt;br /&gt;
0xFFFF902F : Error 0x02&lt;br /&gt;
0xFFFF9030 : Error 0x02&lt;br /&gt;
0xFFFF9031 : Error 0x02&lt;br /&gt;
0xFFFF9032 : Error 0x02&lt;br /&gt;
0xFFFF9033 : Error 0x02&lt;br /&gt;
0xFFFF9034 : Error 0x02&lt;br /&gt;
0xFFFF9035 : Error 0x02&lt;br /&gt;
0xFFFF9036 : Error 0x02&lt;br /&gt;
0xFFFF9037 : Error 0x02&lt;br /&gt;
0xFFFF9038 : Error 0x02&lt;br /&gt;
0xFFFF9039 : Error 0x02&lt;br /&gt;
0xFFFF903A : Error 0x02&lt;br /&gt;
0xFFFF903B : Error 0x02&lt;br /&gt;
0xFFFF903C : Error 0x02&lt;br /&gt;
0xFFFF903D : 0x00&lt;br /&gt;
0xFFFF903E : 0x00&lt;br /&gt;
0xFFFF903F : 0x00&lt;br /&gt;
0xFFFF9040 : Error 0x02&lt;br /&gt;
0xFFFF9041 : Error 0x02&lt;br /&gt;
0xFFFF9042 : 0x00&lt;br /&gt;
0xFFFF9043 : 0x00&lt;br /&gt;
0xFFFF9044 : 0x13&lt;br /&gt;
0xFFFF9045 : 0x00&lt;br /&gt;
0xFFFF9046 : 0x00&lt;br /&gt;
0xFFFF9047 : 0x06&lt;br /&gt;
0xFFFF9048 : 0x00&lt;br /&gt;
0xFFFF9049 : 0x00&lt;br /&gt;
0xFFFF904A : 0x13&lt;br /&gt;
0xFFFF904B : 0x00&lt;br /&gt;
0xFFFF904C : 0x00&lt;br /&gt;
0xFFFF904D : 0x06&lt;br /&gt;
0xFFFF904E : Error 0x02&lt;br /&gt;
0xFFFF904F : Error 0x02&lt;br /&gt;
0xFFFF9050 : Error 0x02&lt;br /&gt;
0xFFFF9051 : Error 0x02&lt;br /&gt;
0xFFFF9052 : Error 0x02&lt;br /&gt;
0xFFFF9053 : Error 0x02&lt;br /&gt;
0xFFFF9054 : Error 0x02&lt;br /&gt;
0xFFFF9055 : Error 0x02&lt;br /&gt;
0xFFFF9056 : Error 0x02&lt;br /&gt;
0xFFFF9057 : Error 0x02&lt;br /&gt;
0xFFFF9058 : Error 0x02&lt;br /&gt;
0xFFFF9059 : Error 0x02&lt;br /&gt;
0xFFFF905A : Error 0x02&lt;br /&gt;
0xFFFF905B : Error 0x02&lt;br /&gt;
0xFFFF905C : Error 0x02&lt;br /&gt;
0xFFFF905D : Error 0x02&lt;br /&gt;
0xFFFF905E : Error 0x02&lt;br /&gt;
0xFFFF905F : Error 0x02&lt;br /&gt;
0xFFFF9060 : Error 0x02&lt;br /&gt;
0xFFFF9061 : Error 0x02&lt;br /&gt;
0xFFFF9062 : Error 0x02&lt;br /&gt;
0xFFFF9063 : 0x1E&lt;br /&gt;
0xFFFF9064 : 0x02&lt;br /&gt;
0xFFFF9065 : 0x00&lt;br /&gt;
0xFFFF9066 : Error 0x02&lt;br /&gt;
0xFFFF9067 : 0x02&lt;br /&gt;
0xFFFF9068 : Error 0x02&lt;br /&gt;
0xFFFF9069 : 0x00&lt;br /&gt;
0xFFFF906A : 0x00&lt;br /&gt;
0xFFFF906B : 0x78&lt;br /&gt;
0xFFFF906C : 0x50&lt;br /&gt;
0xFFFF906D : 0x1E&lt;br /&gt;
0xFFFF906E : 0x50&lt;br /&gt;
0xFFFF906F : 0x28&lt;br /&gt;
0xFFFF9070 : 0x00&lt;br /&gt;
0xFFFF9071 : Error 0x02&lt;br /&gt;
0xFFFF9072 : Error 0x02&lt;br /&gt;
0xFFFF9073 : Error 0x02&lt;br /&gt;
0xFFFF9074 : Error 0x02&lt;br /&gt;
0xFFFF9075 : Error 0x02&lt;br /&gt;
0xFFFF9076 : Error 0x02&lt;br /&gt;
0xFFFF9077 : Error 0x02&lt;br /&gt;
0xFFFF9078 : Error 0x02&lt;br /&gt;
0xFFFF9079 : Error 0x02&lt;br /&gt;
0xFFFF907A : Error 0x02&lt;br /&gt;
0xFFFF907B : Error 0x02&lt;br /&gt;
0xFFFF907C : Error 0x02&lt;br /&gt;
0xFFFF907D : Error 0x02&lt;br /&gt;
0xFFFF907E : Error 0x02&lt;br /&gt;
0xFFFF907F : Error 0x02&lt;br /&gt;
0xFFFF9080 : Error 0x02&lt;br /&gt;
0xFFFF9081 : Error 0x02&lt;br /&gt;
0xFFFF9082 : Error 0x02&lt;br /&gt;
0xFFFF9083 : Error 0x02&lt;br /&gt;
0xFFFF9084 : Error 0x02&lt;br /&gt;
0xFFFF9085 : Error 0x02&lt;br /&gt;
0xFFFF9086 : Error 0x02&lt;br /&gt;
0xFFFF9087 : Error 0x02&lt;br /&gt;
0xFFFF9088 : Error 0x02&lt;br /&gt;
0xFFFF9089 : Error 0x02&lt;br /&gt;
0xFFFF908A : Error 0x02&lt;br /&gt;
0xFFFF908B : Error 0x02&lt;br /&gt;
0xFFFF908C : Error 0x02&lt;br /&gt;
0xFFFF908D : Error 0x02&lt;br /&gt;
0xFFFF908E : Error 0x02&lt;br /&gt;
0xFFFF908F : Error 0x02&lt;br /&gt;
0xFFFF9090 : 0x00&lt;br /&gt;
0xFFFF9091 : 0x00&lt;br /&gt;
0xFFFF9092 : 0x00&lt;br /&gt;
0xFFFF9093 : 0x00&lt;br /&gt;
0xFFFF9094 : 0x57&lt;br /&gt;
0xFFFF9095 : 0x00&lt;br /&gt;
0xFFFF9096 : 0x00&lt;br /&gt;
0xFFFF9097 : 0x38&lt;br /&gt;
0xFFFF9098 : 0xEE&lt;br /&gt;
0xFFFF9099 : Error 0x02&lt;br /&gt;
0xFFFF909A : Error 0x02&lt;br /&gt;
0xFFFF909B : Error 0x02&lt;br /&gt;
0xFFFF909C : Error 0x02&lt;br /&gt;
0xFFFF909D : Error 0x02&lt;br /&gt;
0xFFFF909E : Error 0x02&lt;br /&gt;
0xFFFF909F : Error 0x02&lt;br /&gt;
0xFFFF90A0 : 0x00&lt;br /&gt;
0xFFFF90A1 : 0x00&lt;br /&gt;
0xFFFF90A2 : 0x00&lt;br /&gt;
0xFFFF90A3 : 0x00&lt;br /&gt;
0xFFFF90A4 : 0x00&lt;br /&gt;
0xFFFF90A5 : Error 0x02&lt;br /&gt;
0xFFFF90A6 : Error 0x02&lt;br /&gt;
0xFFFF90A7 : Error 0x02&lt;br /&gt;
0xFFFF90A8 : Error 0x02&lt;br /&gt;
0xFFFF90A9 : Error 0x02&lt;br /&gt;
0xFFFF90AA : Error 0x02&lt;br /&gt;
0xFFFF90AB : Error 0x02&lt;br /&gt;
0xFFFF90AC : Error 0x02&lt;br /&gt;
0xFFFF90AD : Error 0x02&lt;br /&gt;
0xFFFF90AE : Error 0x02&lt;br /&gt;
0xFFFF90AF : Error 0x02&lt;br /&gt;
0xFFFF90B0 : 0xD2&lt;br /&gt;
0xFFFF90B1 : 0x60&lt;br /&gt;
0xFFFF90B2 : 0x13&lt;br /&gt;
0xFFFF90B3 : 0x7A&lt;br /&gt;
0xFFFF90B4 : 0x00&lt;br /&gt;
0xFFFF90B5 : 0xA7&lt;br /&gt;
0xFFFF90B6 : 0x89&lt;br /&gt;
0xFFFF90B7 : 0x35&lt;br /&gt;
0xFFFF90B8 : 0x75&lt;br /&gt;
0xFFFF90B9 : 0x87&lt;br /&gt;
0xFFFF90BA : 0x00&lt;br /&gt;
0xFFFF90BB : 0x00&lt;br /&gt;
0xFFFF90BC : Error 0x02&lt;br /&gt;
0xFFFF90BD : 0x00&lt;br /&gt;
0xFFFF90BE : 0x00&lt;br /&gt;
0xFFFF90BF : 0xE0&lt;br /&gt;
0xFFFF90C0 : Error 0x02&lt;br /&gt;
0xFFFF90C1 : Error 0x02&lt;br /&gt;
0xFFFF90C2 : Error 0x02&lt;br /&gt;
0xFFFF90C3 : Error 0x02&lt;br /&gt;
0xFFFF90C4 : Error 0x02&lt;br /&gt;
0xFFFF90C5 : Error 0x02&lt;br /&gt;
0xFFFF90C6 : Error 0x02&lt;br /&gt;
0xFFFF90C7 : Error 0x02&lt;br /&gt;
0xFFFF90C8 : Error 0x02&lt;br /&gt;
0xFFFF90C9 : Error 0x02&lt;br /&gt;
0xFFFF90CA : Error 0x02&lt;br /&gt;
0xFFFF90CB : Error 0x02&lt;br /&gt;
0xFFFF90CC : Error 0x02&lt;br /&gt;
0xFFFF90CD : Error 0x02&lt;br /&gt;
0xFFFF90CE : Error 0x02&lt;br /&gt;
0xFFFF90CF : Error 0x02&lt;br /&gt;
0xFFFF90D0 : Error 0x02&lt;br /&gt;
0xFFFF90D1 : Error 0x02&lt;br /&gt;
0xFFFF90D2 : Error 0x02&lt;br /&gt;
0xFFFF90D3 : Error 0x02&lt;br /&gt;
0xFFFF90D4 : Error 0x02&lt;br /&gt;
0xFFFF90D5 : Error 0x02&lt;br /&gt;
0xFFFF90D6 : Error 0x02&lt;br /&gt;
0xFFFF90D7 : Error 0x02&lt;br /&gt;
0xFFFF90D8 : Error 0x02&lt;br /&gt;
0xFFFF90D9 : Error 0x02&lt;br /&gt;
0xFFFF90DA : Error 0x02&lt;br /&gt;
0xFFFF90DB : Error 0x02&lt;br /&gt;
0xFFFF90DC : Error 0x02&lt;br /&gt;
0xFFFF90DD : Error 0x02&lt;br /&gt;
0xFFFF90DE : Error 0x02&lt;br /&gt;
0xFFFF90DF : Error 0x02&lt;br /&gt;
0xFFFF90E0 : Error 0x02&lt;br /&gt;
0xFFFF90E1 : Error 0x02&lt;br /&gt;
0xFFFF90E2 : Error 0x02&lt;br /&gt;
0xFFFF90E3 : Error 0x02&lt;br /&gt;
0xFFFF90E4 : Error 0x02&lt;br /&gt;
0xFFFF90E5 : Error 0x02&lt;br /&gt;
0xFFFF90E6 : Error 0x02&lt;br /&gt;
0xFFFF90E7 : Error 0x02&lt;br /&gt;
0xFFFF90E8 : Error 0x02&lt;br /&gt;
0xFFFF90E9 : Error 0x02&lt;br /&gt;
0xFFFF90EA : Error 0x02&lt;br /&gt;
0xFFFF90EB : Error 0x02&lt;br /&gt;
0xFFFF90EC : Error 0x02&lt;br /&gt;
0xFFFF90ED : Error 0x02&lt;br /&gt;
0xFFFF90EE : Error 0x02&lt;br /&gt;
0xFFFF90EF : Error 0x02&lt;br /&gt;
0xFFFF90F0 : Error 0x02&lt;br /&gt;
0xFFFF90F1 : Error 0x02&lt;br /&gt;
0xFFFF90F2 : Error 0x02&lt;br /&gt;
0xFFFF90F3 : Error 0x02&lt;br /&gt;
0xFFFF90F4 : Error 0x02&lt;br /&gt;
0xFFFF90F5 : Error 0x02&lt;br /&gt;
0xFFFF90F6 : Error 0x02&lt;br /&gt;
0xFFFF90F7 : Error 0x02&lt;br /&gt;
0xFFFF90F8 : Error 0x02&lt;br /&gt;
0xFFFF90F9 : Error 0x02&lt;br /&gt;
0xFFFF90FA : Error 0x02&lt;br /&gt;
0xFFFF90FB : Error 0x02&lt;br /&gt;
0xFFFF90FC : Error 0x02&lt;br /&gt;
0xFFFF90FD : Error 0x02&lt;br /&gt;
0xFFFF90FE : Error 0x02&lt;br /&gt;
0xFFFF90FF : Error 0x02&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//#include &amp;lt;SoftwareSerial.h&amp;gt;&lt;br /&gt;
//const int SSERIAL_RX_PIN = 10;  //Soft Serial Receive pin&lt;br /&gt;
//const int SSERIAL_TX_PIN = 11;  //Soft Serial Transmit pin&lt;br /&gt;
&lt;br /&gt;
// Create Soft Serial Port object and define pins to use&lt;br /&gt;
//SoftwareSerial RS485Serial(SSERIAL_RX_PIN, SSERIAL_TX_PIN); // RX, TX&lt;br /&gt;
&lt;br /&gt;
#define DEVICE 0x01&lt;br /&gt;
#define BUFS 64   //Buffer size&lt;br /&gt;
short crc;&lt;br /&gt;
byte arry[6] = {0x00, 0x02, 0x02, 0x00, 0x02, 0x00};&lt;br /&gt;
byte Response[BUFS];&lt;br /&gt;
byte Response_size;&lt;br /&gt;
byte countdown = 2;&lt;br /&gt;
//===============================================================================&lt;br /&gt;
//  Initialization&lt;br /&gt;
//===============================================================================&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(115200);           // Start the built-in serial port   &lt;br /&gt;
  Serial1.begin(115200);   // Start the RS485 soft serial port &lt;br /&gt;
  delay(1000);&lt;br /&gt;
  Serial.println();&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
  Response_size=zeroone(Response,0x0002,0x0001 ); //number must be [1-0x07d0]&lt;br /&gt;
 &lt;br /&gt;
  Serial.print(&amp;quot;Size  Redad Respponse  is  : &amp;quot;);&lt;br /&gt;
  Serial.println(Response_size);&lt;br /&gt;
&lt;br /&gt;
  Serial.print(&amp;quot;Response Read Response string is : &amp;quot;);&lt;br /&gt;
  for(byte i=0;i&amp;lt;Response_size;i++)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;0x&amp;quot;);&lt;br /&gt;
    if(Response[i]&amp;lt;16) Serial.print(&amp;quot;0&amp;quot;);&lt;br /&gt;
    Serial.print(Response[i],HEX);&lt;br /&gt;
    Serial.print(&amp;quot; &amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println();&lt;br /&gt;
 /*&lt;br /&gt;
//  for(int k = 0; k &amp;lt; 10; k++)&lt;br /&gt;
 // {&lt;br /&gt;
    Response_size=zerofive(Response,0x0002, HIGH);&lt;br /&gt;
    Serial.print(&amp;quot;Size 05 is  : &amp;quot;);&lt;br /&gt;
    Serial.println(Response_size);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Response 05string is : &amp;quot;);&lt;br /&gt;
    for(byte i=0;i&amp;lt;Response_size;i++)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.print(&amp;quot;0x&amp;quot;);&lt;br /&gt;
      if(Response[i]&amp;lt;16) Serial.print(&amp;quot;0&amp;quot;);&lt;br /&gt;
      Serial.print(Response[i],HEX);&lt;br /&gt;
      Serial.print(&amp;quot; &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    Serial.println();&lt;br /&gt;
    delay(500);&lt;br /&gt;
    /*&lt;br /&gt;
    Response_size=zerofive(Response,0x0002, LOW);&lt;br /&gt;
    Serial.print(&amp;quot;Size is  : &amp;quot;);&lt;br /&gt;
    Serial.println(Response_size);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Response string is : &amp;quot;);&lt;br /&gt;
    for(byte i=0;i&amp;lt;Response_size;i++)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.print(&amp;quot;0x&amp;quot;);&lt;br /&gt;
      if(Response[i]&amp;lt;16) Serial.print(&amp;quot;0&amp;quot;);&lt;br /&gt;
      Serial.print(Response[i],HEX);&lt;br /&gt;
      Serial.print(&amp;quot; &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    */&lt;br /&gt;
    Serial.println();&lt;br /&gt;
    delay(500);&lt;br /&gt;
//  }&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//===============================================================================&lt;br /&gt;
//  Main&lt;br /&gt;
//===============================================================================&lt;br /&gt;
void loop() &lt;br /&gt;
{&lt;br /&gt;
    Response_size=zerofive(Response,0x0002, HIGH);&lt;br /&gt;
    Response_size=zeroone(Response,0x0002,0x0001 ); //number must be [1-0x07d0]&lt;br /&gt;
    if(Response[3]&amp;gt;0)  Serial.println(&amp;quot;Device is ON.&amp;quot;);&lt;br /&gt;
    delay(10000);&lt;br /&gt;
    Response_size=zerofive(Response,0x0002, LOW);&lt;br /&gt;
    Response_size=zeroone(Response,0x0002,0x0001 ); //number must be [1-0x07d0]&lt;br /&gt;
    if(Response[3]==0)  Serial.println(&amp;quot;Device is OFF.&amp;quot;);&lt;br /&gt;
    delay(10000);&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
// Read coils zeroone - Read up to 2000 coils in a call.&lt;br /&gt;
// Requires:&lt;br /&gt;
//   byte rs[] : Respose[]&lt;br /&gt;
//   int start : starting address&lt;br /&gt;
//   int num   : Number of coils between 1..0x07D0&lt;br /&gt;
//&lt;br /&gt;
byte zeroone(byte rs[],int start, int num)&lt;br /&gt;
{&lt;br /&gt;
  byte rq[8];  //Always 8 bytes for 0x01&lt;br /&gt;
  short c; //CRC value&lt;br /&gt;
  byte i, j,sz;  //Counters, size&lt;br /&gt;
&lt;br /&gt;
  //If there are no parameters selected or too many, then error, quit.&lt;br /&gt;
  if(num==0 || num&amp;gt;0x07d0)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Illegal quantity of inputs&amp;quot;);&lt;br /&gt;
    return 0;  &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
  rq[0]=DEVICE; //Global device IO&lt;br /&gt;
  rq[1]=0x01;&lt;br /&gt;
  rq[3]=byte(start&amp;amp;0x00FF);     //starting LSB address&lt;br /&gt;
  rq[2]=byte((start&amp;amp;0xFF00)&amp;gt;&amp;gt;8);//starting MSB address&lt;br /&gt;
  rq[5]=byte(num&amp;amp;0x00FF);       //number of coils LSB&lt;br /&gt;
  rq[4]=byte((num&amp;amp;0xFF00)&amp;gt;&amp;gt;8);  //number of coils MSB&lt;br /&gt;
&lt;br /&gt;
  c = CRC16(rq,6);  //Calculate CRC&lt;br /&gt;
  &lt;br /&gt;
  rq[7]=0x00FF &amp;amp; c; //CRC LSB&lt;br /&gt;
  rq[6]=c&amp;gt;&amp;gt;8;       //CRC MSB&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  //Transmit the Request array onto bus.&lt;br /&gt;
  for(i=0;i&amp;lt;8;i++)&lt;br /&gt;
  {&lt;br /&gt;
    Serial1.write(rq[i]);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //Because the number of coils is in bits and they are returned as bytes, modulo artithmetic&lt;br /&gt;
  //is needed to ensure a fractional byte always rounds upwards to an additioanl byte&lt;br /&gt;
  sz=5+num/8;&lt;br /&gt;
  if(num%8&amp;gt;0) sz++;&lt;br /&gt;
  &lt;br /&gt;
  if(sz&amp;gt;BUFS)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Buffer overflow prevented in 0x01.  Recompile with BUFS to a higher value&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
  for(i=0;i&amp;lt;sz;)&lt;br /&gt;
  {&lt;br /&gt;
    if (Serial1.available())            //Data from the Slave is available&lt;br /&gt;
    {&lt;br /&gt;
      rs[i]=Serial1.read();&lt;br /&gt;
      if(i==1 &amp;amp;&amp;amp; rs[i]==0x83) sz=5; //Error packet is much shorter, always 5.&lt;br /&gt;
      i++;&lt;br /&gt;
    }   &lt;br /&gt;
  }&lt;br /&gt;
  if (rs[1]==0x83)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Remote system threw an error.&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
  c=CRC16(rs,sz-2);&lt;br /&gt;
  if(c!=short((rs[sz-2]&amp;lt;&amp;lt;8 | rs[sz-1])))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CRC error in 'Read Coils' function 0x01&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
  return sz;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read discretes zerotwo - Read up to 2000 discrete inputs in a call.&lt;br /&gt;
// Requires:&lt;br /&gt;
//   byte rs[] : Respose[]&lt;br /&gt;
//   int start : starting address&lt;br /&gt;
//   int num   : Number of inputs between 1..0x07D0&lt;br /&gt;
//&lt;br /&gt;
byte zerotwo(byte rs[], int start, int num)&lt;br /&gt;
{&lt;br /&gt;
  byte rq[8];  //Always 8 bytes&lt;br /&gt;
  short c; //CRC value&lt;br /&gt;
  byte i, j,sz;  //Counters, size&lt;br /&gt;
  &lt;br /&gt;
  rq[0]=DEVICE; //Global device IO&lt;br /&gt;
  rq[1]=0x02;&lt;br /&gt;
  rq[3]=byte(start&amp;amp;0x00FF);  //Starting address LSB&lt;br /&gt;
  rq[2]=byte((start&amp;amp;0xFF00)&amp;gt;&amp;gt;8);  //Starting address MSB&lt;br /&gt;
  rq[5]=byte(num&amp;amp;0x00FF);  //Number of bits LSB&lt;br /&gt;
  rq[4]=byte((num&amp;amp;0xFF00)&amp;gt;&amp;gt;8); //Number of bits MSB&lt;br /&gt;
&lt;br /&gt;
  c = CRC16(rq,6);&lt;br /&gt;
  rq[7]=0x00FF &amp;amp; c;  //CRC LSB written &lt;br /&gt;
  rq[6]=c&amp;gt;&amp;gt;8;       //CRC MSB written&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  //Deliver request to device&lt;br /&gt;
  for(i=0;i&amp;lt;8;i++)&lt;br /&gt;
  {&lt;br /&gt;
    Serial1.write(rq[i]);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //Because the number of coils is in bits and they are returned as bytes, modulo artithmetic&lt;br /&gt;
  //is needed to ensure a fractional byte always rounds upwards to an additional byte&lt;br /&gt;
  sz=5+num/8;&lt;br /&gt;
  if(num%8&amp;gt;0) sz++;&lt;br /&gt;
  &lt;br /&gt;
  if(sz&amp;gt;BUFS)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Buffer overflow prevented in 0x02.  Recompile with BUFS to a higher value&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //Listen for response&lt;br /&gt;
  for(i=0;i&amp;lt;sz;)&lt;br /&gt;
  {&lt;br /&gt;
    if (Serial1.available())            //Data from the Slave is available&lt;br /&gt;
    {&lt;br /&gt;
      rs[i]=Serial1.read();&lt;br /&gt;
      if(i==1 &amp;amp;&amp;amp; rs[i]==0x83) sz=5; //Error packet is much shorter, always 5.&lt;br /&gt;
      i++;&lt;br /&gt;
    }   &lt;br /&gt;
  }&lt;br /&gt;
  if (rs[1]==0x83)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Remote system threw an error.&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //Verify CRC code&lt;br /&gt;
  c=CRC16(rs,sz-2);&lt;br /&gt;
  if(c!=short((rs[sz-2]&amp;lt;&amp;lt;8 | rs[sz-1])))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CRC error in 0x02&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
  return sz;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read Holding Registers zerothree - Read up to 125 registers in a call.&lt;br /&gt;
// Requires:&lt;br /&gt;
//   byte rs[] : Response[]&lt;br /&gt;
//   int start : starting address&lt;br /&gt;
//   int num   : Number of inputs between 1..0x0007D&lt;br /&gt;
//&lt;br /&gt;
//  Note:  Even though the number of inputs will never exceed 8 bits,&lt;br /&gt;
//         the standard requires a 16-bit type cast.&lt;br /&gt;
byte zerothree(byte rs[],int start, int num)&lt;br /&gt;
{&lt;br /&gt;
  byte rq[8];&lt;br /&gt;
  short c; //CRC value&lt;br /&gt;
  byte i, j,sz;  //Counters, size&lt;br /&gt;
&lt;br /&gt;
  if(num==0 || num&amp;gt;0x007d)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Illegal quantity of inputs&amp;quot;);&lt;br /&gt;
    return 0;  &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
  rq[0]=DEVICE; //Global device IO&lt;br /&gt;
  rq[1]=0x03;&lt;br /&gt;
  rq[3]=byte(start&amp;amp;0x00FF);&lt;br /&gt;
  rq[2]=byte((start&amp;amp;0xFF00)&amp;gt;&amp;gt;8);&lt;br /&gt;
  rq[5]=byte(num&amp;amp;0x00FF);&lt;br /&gt;
  rq[4]=0x00;  //The number of registers MSB is always zero&lt;br /&gt;
&lt;br /&gt;
  //Calculate and store CRC&lt;br /&gt;
  c = CRC16(rq,6);&lt;br /&gt;
  rq[7]=0x00FF &amp;amp; c;&lt;br /&gt;
  rq[6]=c&amp;gt;&amp;gt;8;&lt;br /&gt;
&lt;br /&gt;
  //Deliver request to device&lt;br /&gt;
  for(i=0;i&amp;lt;8;i++)&lt;br /&gt;
  {&lt;br /&gt;
    Serial1.write(rq[i]);&lt;br /&gt;
  }&lt;br /&gt;
  sz = 5+num*2;&lt;br /&gt;
  if(sz&amp;gt;BUFS)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Buffer overflow prevented in 0x03.  Recompile with BUFS to a higher value&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
  //Listen for Response&lt;br /&gt;
  for(i=0;i&amp;lt;sz;)&lt;br /&gt;
  {&lt;br /&gt;
    if (Serial1.available())            //Data from the Slave is available&lt;br /&gt;
    {&lt;br /&gt;
      rs[i]=Serial1.read();&lt;br /&gt;
      if(i==1 &amp;amp;&amp;amp; rs[i]==0x83) sz=5;&lt;br /&gt;
      i++;&lt;br /&gt;
    }   &lt;br /&gt;
  }&lt;br /&gt;
  if (rs[1]==0x83)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Remote system threw an error.&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
  c=CRC16(rs,sz-2);&lt;br /&gt;
  if(c!=short((rs[sz-2]&amp;lt;&amp;lt;8 | rs[sz-1])))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CRC error in 0x03&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return sz;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Read Input Registers zerofour - Read up to 125 registers in a call.&lt;br /&gt;
// Requires:&lt;br /&gt;
//   byte rs[] : Response[]&lt;br /&gt;
//   int start : starting address&lt;br /&gt;
//   int num   : Number of inputs between 1..0x0007D&lt;br /&gt;
&lt;br /&gt;
byte zerofour(byte rs[],int start, int num)&lt;br /&gt;
{&lt;br /&gt;
  byte rq[8];  //Always 8 bytes&lt;br /&gt;
  //int addr;&lt;br /&gt;
  //int len;&lt;br /&gt;
  short c; //CRC value&lt;br /&gt;
  byte i, j,sz;  //Counters, size&lt;br /&gt;
&lt;br /&gt;
  if(num==0 || num&amp;gt;0x007d)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Illegal quantity of inputs&amp;quot;);&lt;br /&gt;
    return 0;  &lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  rq[0]=DEVICE; //Global device IO&lt;br /&gt;
  rq[1]=0x04;&lt;br /&gt;
  rq[3]=byte(start&amp;amp;0x00FF);   //LSB of starting register&lt;br /&gt;
  rq[2]=byte((start&amp;amp;0xFF00)&amp;gt;&amp;gt;8);  //MSB of starting register&lt;br /&gt;
  rq[5]=byte(num&amp;amp;0x00FF);&lt;br /&gt;
  rq[4]=0x00;  //This is always zero for this function&lt;br /&gt;
&lt;br /&gt;
  c = CRC16(rq,6);  //Generate CRC&lt;br /&gt;
  rq[7]=0x00FF &amp;amp; c;  //Write LSB of CRC&lt;br /&gt;
  rq[6]=c&amp;gt;&amp;gt;8; //Write MSB of CRC&lt;br /&gt;
&lt;br /&gt;
  //Deliver request to device&lt;br /&gt;
  for(i=0;i&amp;lt;8;i++)&lt;br /&gt;
  {&lt;br /&gt;
    Serial1.write(rq[i]);&lt;br /&gt;
  }&lt;br /&gt;
  sz = 5+num*2;&lt;br /&gt;
  if(sz&amp;gt;BUFS)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Buffer overflow prevented in 0x04.  Recompile with BUFS to a higher value&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
  //Listen for Response&lt;br /&gt;
  for(i=0;i&amp;lt;sz;)&lt;br /&gt;
  {&lt;br /&gt;
    if (Serial1.available())            //Data from the Slave is available&lt;br /&gt;
    {&lt;br /&gt;
      rs[i]=Serial1.read();&lt;br /&gt;
      if(i==1 &amp;amp;&amp;amp; rs[i]==0x83) sz=5;&lt;br /&gt;
      i++;&lt;br /&gt;
    }   &lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if (rs[1]==0x83)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Remote system threw an error.&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
  c=CRC16(rs,sz-2);&lt;br /&gt;
  if(c!=short((rs[sz-2]&amp;lt;&amp;lt;8 | rs[sz-1])))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CRC error in 0x04&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return sz;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Write Single Coil zerofive - Write a coild 0xFF00 or 0x0000.&lt;br /&gt;
// Requires:&lt;br /&gt;
//   byte rs[] : Response[]&lt;br /&gt;
//   int start : starting address&lt;br /&gt;
//   bool set  : State of coil LOW or HIGH&lt;br /&gt;
byte zerofive(byte rs[],int addr, bool set)&lt;br /&gt;
{&lt;br /&gt;
  byte rq[8];  //Always 8 bytes&lt;br /&gt;
  short c; //CRC value&lt;br /&gt;
  byte i, j,sz;  //Counters, size&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
  rq[0]=DEVICE; //Global device IO&lt;br /&gt;
  rq[1]=0x05;&lt;br /&gt;
  rq[3]=byte(addr&amp;amp;0x00FF);&lt;br /&gt;
  rq[2]=byte((addr&amp;amp;0xFF00)&amp;gt;&amp;gt;8);&lt;br /&gt;
  rq[5]=0x00;  //Always zero&lt;br /&gt;
  if(set) rq[4]=0xFF;&lt;br /&gt;
  else rq[4]=0x00;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  c = CRC16(rq,6);&lt;br /&gt;
  rq[7]=0x00FF &amp;amp; c;&lt;br /&gt;
  rq[6]=c&amp;gt;&amp;gt;8;&lt;br /&gt;
&lt;br /&gt;
  //Deliver request to device&lt;br /&gt;
  for(i=0;i&amp;lt;8;i++)&lt;br /&gt;
  {&lt;br /&gt;
    Serial1.write(rq[i]);&lt;br /&gt;
  }&lt;br /&gt;
  sz = 8;  //Always 8 for this function&lt;br /&gt;
  if(sz&amp;gt;BUFS)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Buffer overflow prevented in 0x03.  Recompile with BUFS to a higher value&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //Listen for Response&lt;br /&gt;
  for(i=0;i&amp;lt;sz;)&lt;br /&gt;
  {&lt;br /&gt;
    if (Serial1.available())            //Data from the Slave is available&lt;br /&gt;
    {&lt;br /&gt;
      rs[i]=Serial1.read();&lt;br /&gt;
      if(i==1 &amp;amp;&amp;amp; rs[i]==0x83) sz=5;&lt;br /&gt;
      i++;&lt;br /&gt;
    }   &lt;br /&gt;
  }&lt;br /&gt;
  if (rs[1]==0x83)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Remote system threw an error.&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  c=CRC16(rs,sz-2);&lt;br /&gt;
&lt;br /&gt;
  if(c!=short((rs[sz-2]&amp;lt;&amp;lt;8 | rs[sz-1])))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CRC error in 0x05&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Write multiple registers onezero - Read up to 123 registers in a call.&lt;br /&gt;
// Requires:&lt;br /&gt;
//   byte rs[] : Response[]&lt;br /&gt;
//   int start : starting address&lt;br /&gt;
//   int num   : Number of inputs between 1..0x0007B&lt;br /&gt;
//   byte arr[]: Array containing registers being written&lt;br /&gt;
byte onezero(byte rs[],int start, int num, byte arr[])&lt;br /&gt;
{&lt;br /&gt;
  byte rq[255];&lt;br /&gt;
  short c; //CRC value&lt;br /&gt;
  byte i, j,sz;  //Counters, size&lt;br /&gt;
&lt;br /&gt;
  if(num==0 || num&amp;gt;0x7B)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Invalid number of registers being written in 0x10.&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
  rq[0]=DEVICE; //Global device IO&lt;br /&gt;
  rq[1]=0x10;&lt;br /&gt;
  rq[3]=byte(start&amp;amp;0x00FF);&lt;br /&gt;
  rq[2]=byte((start&amp;amp;0xFF00)&amp;gt;&amp;gt;8);&lt;br /&gt;
  rq[5]=byte(num&amp;amp;0x00FF);&lt;br /&gt;
  rq[4]=0x00;  //always zero&lt;br /&gt;
  rq[6]=num&amp;lt;&amp;lt;1;  //num*2&lt;br /&gt;
&lt;br /&gt;
  for(int i=0;i&amp;lt;(num&amp;lt;&amp;lt;1);i++)&lt;br /&gt;
  {&lt;br /&gt;
    rq[7+i]=arr[i];&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  c = CRC16(rq,7+(num&amp;lt;&amp;lt;1));&lt;br /&gt;
  rq[8+(num&amp;lt;&amp;lt;1)]=0x00FF &amp;amp; c;&lt;br /&gt;
  rq[7+(num&amp;lt;&amp;lt;1)]=c&amp;gt;&amp;gt;8;&lt;br /&gt;
&lt;br /&gt;
  for(i=0;i&amp;lt;9+(num&amp;lt;&amp;lt;1);i++)&lt;br /&gt;
  {&lt;br /&gt;
    Serial1.write(rq[i]);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  sz = 9+(num&amp;lt;&amp;lt;1);  //9 byzes +  2*num&lt;br /&gt;
  if(sz&amp;gt;BUFS)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Buffer overflow prevented in 0x04.  Recompile with BUFS to a higher value&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  sz=8;  //This response is always 8 bytes long&lt;br /&gt;
  //Listen for Response&lt;br /&gt;
  for(i=0;i&amp;lt;sz;)&lt;br /&gt;
  {&lt;br /&gt;
    if (Serial1.available())            //Data from the Slave is available&lt;br /&gt;
    {&lt;br /&gt;
      rs[i]=Serial1.read();&lt;br /&gt;
      if(i==1 &amp;amp;&amp;amp; rs[i]==0x83) sz=5;&lt;br /&gt;
      i++;&lt;br /&gt;
    }   &lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if (rs[1]==0x83)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;Remote system threw an error.&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
  c=CRC16(rs,sz-2);&lt;br /&gt;
  if(c!=short((rs[sz-2]&amp;lt;&amp;lt;8 | rs[sz-1])))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CRC error in 0x04&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
  return sz;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
short CRC16(byte array[],byte s)&lt;br /&gt;
{&lt;br /&gt;
  static const byte auchCRCHi[] = {&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,&lt;br /&gt;
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40} ; &lt;br /&gt;
&lt;br /&gt;
  static const byte auchCRCLo[] = {&lt;br /&gt;
        0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2,&lt;br /&gt;
        0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04,&lt;br /&gt;
        0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,&lt;br /&gt;
        0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8,&lt;br /&gt;
        0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,&lt;br /&gt;
        0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,&lt;br /&gt;
        0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6,&lt;br /&gt;
        0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10,&lt;br /&gt;
        0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,&lt;br /&gt;
        0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,&lt;br /&gt;
        0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE,&lt;br /&gt;
        0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,&lt;br /&gt;
        0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA,&lt;br /&gt;
        0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C,&lt;br /&gt;
        0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,&lt;br /&gt;
        0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0,&lt;br /&gt;
        0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62,&lt;br /&gt;
        0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,&lt;br /&gt;
        0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE,&lt;br /&gt;
        0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,&lt;br /&gt;
        0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,&lt;br /&gt;
        0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C,&lt;br /&gt;
        0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76,&lt;br /&gt;
        0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,&lt;br /&gt;
        0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,&lt;br /&gt;
        0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54,&lt;br /&gt;
        0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,&lt;br /&gt;
        0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98,&lt;br /&gt;
        0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A,&lt;br /&gt;
        0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,&lt;br /&gt;
        0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86,&lt;br /&gt;
        0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40} ;&lt;br /&gt;
&lt;br /&gt;
  byte uchCRCHi = 0xFF;&lt;br /&gt;
  byte uchCRCLo = 0xFF;&lt;br /&gt;
  byte uIndex;&lt;br /&gt;
&lt;br /&gt;
  while(s--)&lt;br /&gt;
  {&lt;br /&gt;
    uIndex = uchCRCHi ^ *array++ ;&lt;br /&gt;
    uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;&lt;br /&gt;
    uchCRCLo = auchCRCLo[uIndex] ;&lt;br /&gt;
  }&lt;br /&gt;
  return short(uchCRCHi &amp;lt;&amp;lt; 8 | uchCRCLo);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=RS485_Master_Example&amp;diff=58</id>
		<title>RS485 Master Example</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=RS485_Master_Example&amp;diff=58"/>
		<updated>2020-11-16T17:44:58Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: Created page with &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt; //#include &amp;lt;SoftwareSerial.h&amp;gt; //const int SSERIAL_RX_PIN = 10;  //Soft Serial Receive pin //const int SSERIAL_TX_PIN = 11;  //Soft Serial Transmit...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
//#include &amp;lt;SoftwareSerial.h&amp;gt;&lt;br /&gt;
//const int SSERIAL_RX_PIN = 10;  //Soft Serial Receive pin&lt;br /&gt;
//const int SSERIAL_TX_PIN = 11;  //Soft Serial Transmit pin&lt;br /&gt;
&lt;br /&gt;
// Create Soft Serial Port object and define pins to use&lt;br /&gt;
//SoftwareSerial RS485Serial(SSERIAL_RX_PIN, SSERIAL_TX_PIN); // RX, TX&lt;br /&gt;
&lt;br /&gt;
int byteReceived;&lt;br /&gt;
//===============================================================================&lt;br /&gt;
//  Initialization&lt;br /&gt;
//===============================================================================&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(115200);           // Start the built-in serial port&lt;br /&gt;
  Serial.println(&amp;quot;Master Device&amp;quot;);&lt;br /&gt;
  Serial.println(&amp;quot;Type in upper window, press ENTER&amp;quot;);&lt;br /&gt;
   &lt;br /&gt;
  Serial1.begin(115200);   // Start the RS485 soft serial port &lt;br /&gt;
}&lt;br /&gt;
//===============================================================================&lt;br /&gt;
//  Main&lt;br /&gt;
//===============================================================================&lt;br /&gt;
void loop() &lt;br /&gt;
{&lt;br /&gt;
  if (Serial.available())         // A char(byte) has been entered in the Serial Monitor&lt;br /&gt;
  {&lt;br /&gt;
    byteReceived = Serial.read();                   // Read the byte&lt;br /&gt;
    Serial1.write(byteReceived);                 // Send byte to Remote Arduino &lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if (Serial1.available())            //Data from the Slave is available&lt;br /&gt;
   {&lt;br /&gt;
    byteReceived = Serial1.read();    // Read received byte&lt;br /&gt;
 //coomented for diagnostics&lt;br /&gt;
 //Serial.write(byteReceived);           // Show on Serial Monitor&lt;br /&gt;
 Serial.print(micros());&lt;br /&gt;
 Serial.print(' ');&lt;br /&gt;
 Serial.println(byteReceived,HEX);&lt;br /&gt;
   }  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=Arduino_Projects&amp;diff=57</id>
		<title>Arduino Projects</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=Arduino_Projects&amp;diff=57"/>
		<updated>2020-11-16T17:44:12Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: added rs485 code&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[QR Code generation with 3.5&amp;quot; TFT Touch screen on Arudino MEGA2560]]&lt;br /&gt;
&lt;br /&gt;
[[CAN bus battery monitor with 3.5&amp;quot; TFT Touch screen on Arudino MEGA2560]]&lt;br /&gt;
&lt;br /&gt;
[[Can bus battery monitor with OLED]]&lt;br /&gt;
&lt;br /&gt;
[[Can bus battery monitor]]&lt;br /&gt;
&lt;br /&gt;
[[OLED Display]]&lt;br /&gt;
&lt;br /&gt;
[[OLED Display SSD1306 i2c 128x64 demo]]&lt;br /&gt;
&lt;br /&gt;
[[LCD demo]]&lt;br /&gt;
&lt;br /&gt;
[[RS485 Master Example]]&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=44</id>
		<title>CAN bus battery monitor with 3.5&quot; TFT Touch screen on Arudino MEGA2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=44"/>
		<updated>2020-11-05T00:37:07Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */ adjusted LCD, Vsum positions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
Only Displays Packs 0-3. Does not autodetect modules. Snake Game easter egg not yet inmplemented&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;quot;mcp_can.h&amp;quot;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS 4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS 8     //Hazardous to modify&lt;br /&gt;
#define REFRESH 1000   //Refresh rate display&lt;br /&gt;
#define ALARM 3.660    //Alarm threshold&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x0821&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RED 1111 1000 0000 0000&lt;br /&gt;
//BLU 0000 0000 0001 1111&lt;br /&gt;
//GRE 0000 0111 1110 0000&lt;br /&gt;
//GRY 0000 1000 0010 0001 = 0x0821&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
boolean ledON = 1;&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
float temp[NUMPACKS][NUMCELLS];&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int tempdisplay[NUMPACKS][NUMCELLS];&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
&lt;br /&gt;
unsigned char bufA[10];&lt;br /&gt;
unsigned char buf0[10];&lt;br /&gt;
unsigned char buf3[10];&lt;br /&gt;
unsigned char buf5[10];&lt;br /&gt;
unsigned char buf20[10];&lt;br /&gt;
unsigned char buf21[10];&lt;br /&gt;
unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  //mylcd.Fill_Screen(BLACK);&lt;br /&gt;
  //mylcd.Set_Text_Mode(0);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temp[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temp[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temp[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temp[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temp[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temp code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temp code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf3[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf5[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          bufA[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf0[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][7] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][6] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][5] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
              buf20[i] = buf[i];&lt;br /&gt;
          } &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][4] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][3] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][2] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf21[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][1] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][0] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf22[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
        //TestTemp();&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)   //KILLER LINE&lt;br /&gt;
              //digitalWrite(49,1);&lt;br /&gt;
              buzzer=HIGH;&lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
&lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode=1)&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    //display 1 times string&lt;br /&gt;
  mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
  mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
  mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
  //Draw Packs&lt;br /&gt;
  //Pack 1&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,42 , 150, 191);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(11, 62, 149, 62);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,193 , 150, 214);&lt;br /&gt;
  //Pack 2&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,42 , 310, 191);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(171, 62, 309, 62);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,193, 310, 214);&lt;br /&gt;
  //Pack 3&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,234 , 150, 386);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(11, 254, 149, 254);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,384 , 150, 407);&lt;br /&gt;
  //Pack 4&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(170, 234 , 310, 386);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(171, 254, 309, 254);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,384, 310, 407);&lt;br /&gt;
  //Fill Text&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Set_Text_Mode(1);&lt;br /&gt;
  //mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_Size(3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,24,320);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,25,320);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,26,320);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  //mylcd.Set_Text_Mode(1);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*0); &lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; x04     (-)   x20     (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*10);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*11);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*12); &lt;br /&gt;
  //mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; x06     (-)   x22     (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
  //mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; (+)       V  (+)       V&amp;quot;, 4, 38+16*22);&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*23);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*24);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*25);  &lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*26);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(void)&lt;br /&gt;
{&lt;br /&gt;
//  float voltage_[5][8]={{1.001,2.001,3.001,4.001,5.001,6.001,7.001,8.001},{1.002,2.002,3.002,4.002,5.002,6.002,7.002,8.002},{1.003,2.003,3.003,4.003,5.003,6.003,7.003,8.003},{1.004,2.004,3.004,4.004,5.004,6.004,7.004,8.004},{1.005,2.005,3.005,4.005,5.005,6.005,7.005,8.005}}; &lt;br /&gt;
  long st, fn;&lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(c==7)&lt;br /&gt;
    { &lt;br /&gt;
      mylcd.Set_Text_Mode(0);&lt;br /&gt;
      mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
      mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
      mylcd.Print_Number_Float(sum[p], 3, xc+60, yc+22, '.', 0, ' ');&lt;br /&gt;
      mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    }&lt;br /&gt;
  tempdisplay[p][c] = (int) temp[p][c];&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(tempdisplay[p][c], xc+98,yc,2, ' ', 10);&lt;br /&gt;
&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw)&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit&lt;br /&gt;
  return (raw*1.555)-26.0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void TestTemp(void)&lt;br /&gt;
{&lt;br /&gt;
  int i,j;&lt;br /&gt;
  Serial.println(&amp;quot;Temperatures&amp;quot;);&lt;br /&gt;
  for(i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Pack &amp;quot;);&lt;br /&gt;
    Serial.print(i+1);&lt;br /&gt;
    Serial.print(&amp;quot; : ( &amp;quot;);&lt;br /&gt;
    for(j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.print(temp[i][j]);&lt;br /&gt;
      Serial.print(&amp;quot; , &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    Serial.println(&amp;quot; )&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=43</id>
		<title>CAN bus battery monitor with 3.5&quot; TFT Touch screen on Arudino MEGA2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=43"/>
		<updated>2020-11-05T00:33:38Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */ Voltage array printed in but has issue filling with values&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
Only Displays Packs 0-3. Does not autodetect modules. Snake Game easter egg not yet inmplemented&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;quot;mcp_can.h&amp;quot;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS 4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS 8     //Hazardous to modify&lt;br /&gt;
#define REFRESH 1000   //Refresh rate display&lt;br /&gt;
#define ALARM 3.660    //Alarm threshold&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x0821&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RED 1111 1000 0000 0000&lt;br /&gt;
//BLU 0000 0000 0001 1111&lt;br /&gt;
//GRE 0000 0111 1110 0000&lt;br /&gt;
//GRY 0000 1000 0010 0001 = 0x0821&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
boolean ledON = 1;&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
float temp[NUMPACKS][NUMCELLS];&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int tempdisplay[NUMPACKS][NUMCELLS];&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
&lt;br /&gt;
unsigned char bufA[10];&lt;br /&gt;
unsigned char buf0[10];&lt;br /&gt;
unsigned char buf3[10];&lt;br /&gt;
unsigned char buf5[10];&lt;br /&gt;
unsigned char buf20[10];&lt;br /&gt;
unsigned char buf21[10];&lt;br /&gt;
unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  //mylcd.Fill_Screen(BLACK);&lt;br /&gt;
  //mylcd.Set_Text_Mode(0);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temp[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temp[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temp[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temp[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temp[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temp code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temp code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf3[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf5[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          bufA[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf0[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][7] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][6] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][5] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
              buf20[i] = buf[i];&lt;br /&gt;
          } &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][4] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][3] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][2] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf21[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][1] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][0] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf22[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
        //TestTemp();&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)   //KILLER LINE&lt;br /&gt;
              //digitalWrite(49,1);&lt;br /&gt;
              buzzer=HIGH;&lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
&lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode=1)&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    //display 1 times string&lt;br /&gt;
  mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
  mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
  mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
  //Draw Packs&lt;br /&gt;
  //Pack 1&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,42 , 150, 191);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(11, 62, 149, 62);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,193 , 150, 214);&lt;br /&gt;
  //Pack 2&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,42 , 310, 191);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(171, 62, 309, 62);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,193, 310, 214);&lt;br /&gt;
  //Pack 3&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,234 , 150, 386);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(11, 254, 149, 254);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,384 , 150, 407);&lt;br /&gt;
  //Pack 4&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(170, 234 , 310, 386);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(171, 254, 309, 254);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,384, 310, 407);&lt;br /&gt;
  //Fill Text&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Set_Text_Mode(1);&lt;br /&gt;
  //mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_Size(3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,24,320);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,25,320);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,26,320);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  //mylcd.Set_Text_Mode(1);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*0); &lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; x04     (-)   x20     (-)&amp;quot;, 4, 30+16*1);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; (+)          (+)     &amp;quot;, 4, 38+16*10);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*11);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*12); &lt;br /&gt;
  //mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; x06     (-)   x22     (-)&amp;quot;, 4, 30+16*13);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
  //mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; (+)          (+)        &amp;quot;, 4, 38+16*22);&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*23);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*24);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*25);  &lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*26);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(void)&lt;br /&gt;
{&lt;br /&gt;
//  float voltage_[5][8]={{1.001,2.001,3.001,4.001,5.001,6.001,7.001,8.001},{1.002,2.002,3.002,4.002,5.002,6.002,7.002,8.002},{1.003,2.003,3.003,4.003,5.003,6.003,7.003,8.003},{1.004,2.004,3.004,4.004,5.004,6.004,7.004,8.004},{1.005,2.005,3.005,4.005,5.005,6.005,7.005,8.005}}; &lt;br /&gt;
  long st, fn;&lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  if(c==7)&lt;br /&gt;
    { &lt;br /&gt;
      mylcd.Set_Text_Mode(0);&lt;br /&gt;
      mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
      mylcd.Set_Text_Back_colour(RED);&lt;br /&gt;
      mylcd.Print_Number_Float(sum[p], 3, xc+40, yc+22, '.', 0, ' ');&lt;br /&gt;
      mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
    }&lt;br /&gt;
  tempdisplay[p][c] = (int) temp[p][c];&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(tempdisplay[p][c], xc+98,yc,2, ' ', 10);&lt;br /&gt;
&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw)&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit&lt;br /&gt;
  return (raw*1.555)-26.0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void TestTemp(void)&lt;br /&gt;
{&lt;br /&gt;
  int i,j;&lt;br /&gt;
  Serial.println(&amp;quot;Temperatures&amp;quot;);&lt;br /&gt;
  for(i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Pack &amp;quot;);&lt;br /&gt;
    Serial.print(i+1);&lt;br /&gt;
    Serial.print(&amp;quot; : ( &amp;quot;);&lt;br /&gt;
    for(j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.print(temp[i][j]);&lt;br /&gt;
      Serial.print(&amp;quot; , &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    Serial.println(&amp;quot; )&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=42</id>
		<title>CAN bus battery monitor with 3.5&quot; TFT Touch screen on Arudino MEGA2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=42"/>
		<updated>2020-11-04T23:46:01Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
Only Displays Packs 0-3. Does not autodetect modules. Snake Game easter egg not yet inmplemented&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;quot;mcp_can.h&amp;quot;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS 4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS 8     //Hazardous to modify&lt;br /&gt;
#define REFRESH 1000   //Refresh rate display&lt;br /&gt;
#define ALARM 3.660    //Alarm threshold&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x0821&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RED 1111 1000 0000 0000&lt;br /&gt;
//BLU 0000 0000 0001 1111&lt;br /&gt;
//GRE 0000 0111 1110 0000&lt;br /&gt;
//GRY 0000 1000 0010 0001 = 0x0821&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
boolean ledON = 1;&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
float temp[NUMPACKS][NUMCELLS];&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int tempdisplay[NUMPACKS][NUMCELLS];&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
bool msg5 = LOW;&lt;br /&gt;
&lt;br /&gt;
unsigned char bufA[10];&lt;br /&gt;
unsigned char buf0[10];&lt;br /&gt;
unsigned char buf3[10];&lt;br /&gt;
unsigned char buf5[10];&lt;br /&gt;
unsigned char buf20[10];&lt;br /&gt;
unsigned char buf21[10];&lt;br /&gt;
unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  //mylcd.Fill_Screen(BLACK);&lt;br /&gt;
  //mylcd.Set_Text_Mode(0);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temp[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temp[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-1;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temp[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temp[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          temp[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temp code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temp code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf3[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf5[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          bufA[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf0[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][7] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][6] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][5] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
              buf20[i] = buf[i];&lt;br /&gt;
          } &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][4] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][3] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][2] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf21[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][1] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][0] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf22[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
        //TestTemp();&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)   //KILLER LINE&lt;br /&gt;
              //digitalWrite(49,1);&lt;br /&gt;
              buzzer=HIGH;&lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
&lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        /*&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
        */&lt;br /&gt;
        //END Dump cell voltages to CSV&lt;br /&gt;
        &lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode=1)&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    //display 1 times string&lt;br /&gt;
  mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
  mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
  mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
  //Draw Packs&lt;br /&gt;
  //Pack 1&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,42 , 150, 191);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(11, 62, 149, 62);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,193 , 150, 214);&lt;br /&gt;
  //Pack 2&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,42 , 310, 191);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(171, 62, 309, 62);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,193, 310, 214);&lt;br /&gt;
  //Pack 3&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,234 , 150, 386);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(11, 254, 149, 254);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,388 , 150, 407);&lt;br /&gt;
  //Pack 4&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(170, 234 , 310, 386);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(171, 254, 309, 254);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,388, 310, 407);&lt;br /&gt;
  //Fill Text&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Set_Text_Mode(1);&lt;br /&gt;
  //mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_Size(3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,24,320);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,25,320);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,26,320);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  //mylcd.Set_Text_Mode(1);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*0); &lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; x04 (-)       x20 (-)    &amp;quot;, 4, 30+16*1);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;     (+)          (+)     &amp;quot;, 4, 38+16*10);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*11);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*12); &lt;br /&gt;
  //mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; x06 (-)       x22 (-)    &amp;quot;, 4, 30+16*13);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
  //mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;     (+)          (+)     &amp;quot;, 4, 38+16*22);&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*23);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*24);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*25);  &lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*26);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(void)&lt;br /&gt;
{&lt;br /&gt;
//  float voltage_[5][8]={{1.001,2.001,3.001,4.001,5.001,6.001,7.001,8.001},{1.002,2.002,3.002,4.002,5.002,6.002,7.002,8.002},{1.003,2.003,3.003,4.003,5.003,6.003,7.003,8.003},{1.004,2.004,3.004,4.004,5.004,6.004,7.004,8.004},{1.005,2.005,3.005,4.005,5.005,6.005,7.005,8.005}}; &lt;br /&gt;
  long st, fn;&lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  tempdisplay[p][c] = (int) temp[p][c];&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(tempdisplay[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw)&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit&lt;br /&gt;
  return (raw*1.555)-26.0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void TestTemp(void)&lt;br /&gt;
{&lt;br /&gt;
  int i,j;&lt;br /&gt;
  Serial.println(&amp;quot;Temperatures&amp;quot;);&lt;br /&gt;
  for(i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Pack &amp;quot;);&lt;br /&gt;
    Serial.print(i+1);&lt;br /&gt;
    Serial.print(&amp;quot; : ( &amp;quot;);&lt;br /&gt;
    for(j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.print(temp[i][j]);&lt;br /&gt;
      Serial.print(&amp;quot; , &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    Serial.println(&amp;quot; )&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=40</id>
		<title>CAN bus battery monitor with 3.5&quot; TFT Touch screen on Arudino MEGA2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=40"/>
		<updated>2020-11-04T22:38:33Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */ Added temperature display&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
Only Displays Packs 0-3. Does not autodetect modules. Snake Game easter egg not yet inmplemented&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;quot;mcp_can.h&amp;quot;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
#include &amp;lt;TouchScreen.h&amp;gt; //touch library&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS 4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS 8     //Hazardous to modify&lt;br /&gt;
#define REFRESH 1000   //Refresh rate display&lt;br /&gt;
#define ALARM 3.660    //Alarm threshold&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x0821&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RED 1111 1000 0000 0000&lt;br /&gt;
//BLU 0000 0000 0001 1111&lt;br /&gt;
//GRE 0000 0111 1110 0000&lt;br /&gt;
//GRY 0000 1000 0010 0001 = 0x0821&lt;br /&gt;
&lt;br /&gt;
//Touchscreen&lt;br /&gt;
#define YP A3  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define XM A2  // must be an analog pin, use &amp;quot;An&amp;quot; notation!&lt;br /&gt;
#define YM 9   // can be a digital pin&lt;br /&gt;
#define XP 8   // can be a digital pin&lt;br /&gt;
#define MINPRESSURE 10&lt;br /&gt;
#define MAXPRESSURE 1000&lt;br /&gt;
#define TS_MINX 906&lt;br /&gt;
#define TS_MAXX 116&lt;br /&gt;
#define TS_MINY 92&lt;br /&gt;
#define TS_MAXY 952&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
boolean ledON = 1;&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
float temp[NUMPACKS][NUMCELLS];&lt;br /&gt;
int tempdisplay[NUMPACKS][NUMCELLS];&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
&lt;br /&gt;
unsigned char bufA[10];&lt;br /&gt;
unsigned char buf0[10];&lt;br /&gt;
unsigned char buf3[10];&lt;br /&gt;
unsigned char buf5[10];&lt;br /&gt;
unsigned char buf20[10];&lt;br /&gt;
unsigned char buf21[10];&lt;br /&gt;
unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
TouchScreen ts = TouchScreen(XP,YP, XM, YM, 300);&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  //mylcd.Fill_Screen(BLACK);&lt;br /&gt;
  //mylcd.Set_Text_Mode(0);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
      temp[i][j]=0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool msg05temp_enable = LOW;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  //WARNING - Touch screen may be blocking&lt;br /&gt;
  digitalWrite(13, HIGH);&lt;br /&gt;
  TSPoint p = ts.getPoint();&lt;br /&gt;
  digitalWrite(13, LOW);&lt;br /&gt;
  pinMode(XM, OUTPUT);&lt;br /&gt;
  pinMode(YP, OUTPUT);&lt;br /&gt;
  if (p.z &amp;gt; MINPRESSURE &amp;amp;&amp;amp; p.z &amp;lt; MAXPRESSURE)&lt;br /&gt;
  {&lt;br /&gt;
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);&lt;br /&gt;
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);&lt;br /&gt;
    p.x = map(p.x, TS_MINX, TS_MAXX, mylcd.Get_Display_Width(),0);&lt;br /&gt;
    p.y = map(p.y, TS_MINY, TS_MAXY, mylcd.Get_Display_Height(),0);&lt;br /&gt;
&lt;br /&gt;
    Serial.print(&amp;quot;Touch detect x=&amp;quot;);&lt;br /&gt;
    Serial.print(p.x);&lt;br /&gt;
    Serial.print(&amp;quot; y=&amp;quot;);&lt;br /&gt;
    Serial.println(p.y);   &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {        &lt;br /&gt;
        //Copy seven values to temp[][]&lt;br /&gt;
        if(buf[0]==0)&lt;br /&gt;
        {&lt;br /&gt;
          for(int i=0;i&amp;lt;NUMCELLS-2;i++)&lt;br /&gt;
          {&lt;br /&gt;
            temp[slot][i]=tempconvert(buf[i+1]); //i+1 because buf[0] is a count register&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        //Copy one value to temp[][0] wich is cell 1.&lt;br /&gt;
        if(buf[0]==1)&lt;br /&gt;
        {&lt;br /&gt;
          msg05temp_enable = HIGH;&lt;br /&gt;
        }&lt;br /&gt;
        //unknown temp code&lt;br /&gt;
        if(buf[0]&amp;gt;1)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.println(&amp;quot;Unknown Temp code&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf3[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 5&lt;br /&gt;
      else if (msgID == 0x00000500)&lt;br /&gt;
      {&lt;br /&gt;
        //This event prevents 0 from being written to screen&lt;br /&gt;
        if(msg05temp_enable)&lt;br /&gt;
        {&lt;br /&gt;
          temp[slot][7]=tempconvert(buf[1]);&lt;br /&gt;
        }&lt;br /&gt;
        msg05temp_enable = LOW;&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf5[i] = buf[i];&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          bufA[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf0[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][7] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][6] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][5] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
              buf20[i] = buf[i];&lt;br /&gt;
          } &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][4] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][3] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][2] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf21[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][1] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][0] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf22[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
       TestTemp();&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)   //KILLER LINE&lt;br /&gt;
              //digitalWrite(49,1);&lt;br /&gt;
              buzzer=HIGH;&lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
&lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode=1)&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    //display 1 times string&lt;br /&gt;
  mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
  mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
  mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
  //Draw Packs&lt;br /&gt;
  //Pack 1&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,42 , 150, 191);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(11, 62, 149, 62);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,193 , 150, 214);&lt;br /&gt;
  //Pack 2&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,42 , 310, 191);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(171, 62, 309, 62);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,193, 310, 214);&lt;br /&gt;
  //Pack 3&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,234 , 150, 386);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(11, 254, 149, 254);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,388 , 150, 407);&lt;br /&gt;
  //Pack 4&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(170, 234 , 310, 386);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(171, 254, 309, 254);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,388, 310, 407);&lt;br /&gt;
  //Fill Text&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Set_Text_Mode(1);&lt;br /&gt;
  //mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_Size(3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,24,320);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,25,320);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,26,320);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  //mylcd.Set_Text_Mode(1);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*0); &lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; x04 (-)       x20 (-)    &amp;quot;, 4, 30+16*1);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;     (+) .         (+)     &amp;quot;, 4, 38+16*10);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*11);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*12); &lt;br /&gt;
  //mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; x06 (-)       x22 (-)    &amp;quot;, 4, 30+16*13);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
  //mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;     (+)          (+)     &amp;quot;, 4, 38+16*22);&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*23);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*24);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*25);  &lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*26);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(void)&lt;br /&gt;
{&lt;br /&gt;
//  float voltage_[5][8]={{1.001,2.001,3.001,4.001,5.001,6.001,7.001,8.001},{1.002,2.002,3.002,4.002,5.002,6.002,7.002,8.002},{1.003,2.003,3.003,4.003,5.003,6.003,7.003,8.003},{1.004,2.004,3.004,4.004,5.004,6.004,7.004,8.004},{1.005,2.005,3.005,4.005,5.005,6.005,7.005,8.005}}; &lt;br /&gt;
  long st, fn;&lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
  tempdisplay[p][c] = (int) temp[p][c];&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Int(tempdisplay[p][c], xc+96,yc,2, ' ', 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
char tempconvert(char raw)&lt;br /&gt;
{&lt;br /&gt;
  //Fahrenheit&lt;br /&gt;
  return (raw*1.555)-26.0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void TestTemp(void)&lt;br /&gt;
{&lt;br /&gt;
  int i,j;&lt;br /&gt;
  Serial.println(&amp;quot;Temperatures&amp;quot;);&lt;br /&gt;
  for(i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Pack &amp;quot;);&lt;br /&gt;
    Serial.print(i+1);&lt;br /&gt;
    Serial.print(&amp;quot; : ( &amp;quot;);&lt;br /&gt;
    for(j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.print(temp[i][j]);&lt;br /&gt;
      Serial.print(&amp;quot; , &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    Serial.println(&amp;quot; )&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=33</id>
		<title>CAN bus battery monitor with 3.5&quot; TFT Touch screen on Arudino MEGA2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=33"/>
		<updated>2020-11-04T20:04:22Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */ Text positions were moved to accommodate temperature readings&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
Only Displays Packs 0-3. Does not autodetect modules. Snake Game easter egg not yet inmplemented&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;quot;mcp_can.h&amp;quot;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS 4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS 8     //Hazardous to modify&lt;br /&gt;
#define REFRESH 1000   //Refresh rate display&lt;br /&gt;
#define ALARM 3.660    //Alarm threshold&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x0821&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RED 1111 1000 0000 0000&lt;br /&gt;
//BLU 0000 0000 0001 1111&lt;br /&gt;
//GRE 0000 0111 1110 0000&lt;br /&gt;
//GRY 0000 1000 0010 0001 = 0x0821&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
boolean ledON = 1;&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
&lt;br /&gt;
unsigned char bufA[10];&lt;br /&gt;
unsigned char buf0[10];&lt;br /&gt;
unsigned char buf3[10];&lt;br /&gt;
unsigned char buf5[10];&lt;br /&gt;
unsigned char buf20[10];&lt;br /&gt;
unsigned char buf21[10];&lt;br /&gt;
unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  //mylcd.Fill_Screen(BLACK);&lt;br /&gt;
  //mylcd.Set_Text_Mode(0);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf3[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      else if (msgID == 0x00000500)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf5[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          bufA[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf0[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][7] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][6] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][5] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
              buf20[i] = buf[i];&lt;br /&gt;
          } &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][4] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][3] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][2] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf21[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][1] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][0] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf22[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)   //KILLER LINE&lt;br /&gt;
              //digitalWrite(49,1);&lt;br /&gt;
              buzzer=HIGH;&lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
&lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode=1)&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    //display 1 times string&lt;br /&gt;
  mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
  mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
  mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
  //Draw Packs&lt;br /&gt;
  //Pack 1&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,42 , 150, 191);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(11, 62, 149, 62);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,193 , 150, 214);&lt;br /&gt;
  //Pack 2&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,42 , 310, 191);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(171, 62, 309, 62);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,193, 310, 214);&lt;br /&gt;
  //Pack 3&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,234 , 150, 386);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(11, 254, 149, 254);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,388 , 150, 407);&lt;br /&gt;
  //Pack 4&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(170, 234 , 310, 386);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(171, 254, 309, 254);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(170,388, 310, 407);&lt;br /&gt;
  //Fill Text&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Set_Text_Mode(1);&lt;br /&gt;
  //mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_Size(3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,24,320);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,25,320);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,26,320);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  //mylcd.Set_Text_Mode(1);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*0); &lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; x04 (-)       x20 (-)    &amp;quot;, 4, 30+16*1);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*4);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*5);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*6);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*7);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*8);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*9);&lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;     (+) .         (+)     &amp;quot;, 4, 38+16*10);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*11);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*12); &lt;br /&gt;
  //mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; x06 (-)       x22 (-)    &amp;quot;, 4, 30+16*13);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*14);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*15);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*16);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*17);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*18);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*19);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*20);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; -.---V  --F  -.---V  --F&amp;quot;, 4, 32+16*21);&lt;br /&gt;
  //mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;     (+)          (+)     &amp;quot;, 4, 38+16*22);&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*23);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*24);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*25);  &lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*26);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(void)&lt;br /&gt;
{&lt;br /&gt;
//  float voltage_[5][8]={{1.001,2.001,3.001,4.001,5.001,6.001,7.001,8.001},{1.002,2.002,3.002,4.002,5.002,6.002,7.002,8.002},{1.003,2.003,3.003,4.003,5.003,6.003,7.003,8.003},{1.004,2.004,3.004,4.004,5.004,6.004,7.004,8.004},{1.005,2.005,3.005,4.005,5.005,6.005,7.005,8.005}}; &lt;br /&gt;
  long st, fn;&lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=14;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=172;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=29</id>
		<title>CAN bus battery monitor with 3.5&quot; TFT Touch screen on Arudino MEGA2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=29"/>
		<updated>2020-11-04T06:20:01Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */ removed arithmetic to save clock cycles&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
Only Displays Packs 0-3. Does not autodetect modules. Snake Game easter egg not yet inmplemented&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;quot;mcp_can.h&amp;quot;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS 4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS 8     //Hazardous to modify&lt;br /&gt;
#define REFRESH 1000   //Refresh rate display&lt;br /&gt;
#define ALARM 3.660    //Alarm threshold&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x0821&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RED 1111 1000 0000 0000&lt;br /&gt;
//BLU 0000 0000 0001 1111&lt;br /&gt;
//GRE 0000 0111 1110 0000&lt;br /&gt;
//GRY 0000 1000 0010 0001 = 0x0821&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
boolean ledON = 1;&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
&lt;br /&gt;
unsigned char bufA[10];&lt;br /&gt;
unsigned char buf0[10];&lt;br /&gt;
unsigned char buf3[10];&lt;br /&gt;
unsigned char buf5[10];&lt;br /&gt;
unsigned char buf20[10];&lt;br /&gt;
unsigned char buf21[10];&lt;br /&gt;
unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  //mylcd.Fill_Screen(BLACK);&lt;br /&gt;
  //mylcd.Set_Text_Mode(0);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf3[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      else if (msgID == 0x00000500)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf5[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          bufA[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf0[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][7] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][6] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][5] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
              buf20[i] = buf[i];&lt;br /&gt;
          } &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][4] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][3] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][2] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf21[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][1] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][0] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf22[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)   //KILLER LINE&lt;br /&gt;
              //digitalWrite(49,1);&lt;br /&gt;
              buzzer=HIGH;&lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
&lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode=1)&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    //display 1 times string&lt;br /&gt;
  mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
  mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
  mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
  //Draw Packs&lt;br /&gt;
  //Pack 1&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,42 , 150, 191);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(11, 62, 149, 62);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,193 , 150, 214);&lt;br /&gt;
  //Pack 2&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(180,42 , 310, 191);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(181, 62, 309, 62);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(180,193, 310, 214);&lt;br /&gt;
  //Pack 3&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,234 , 150, 386);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(11, 254, 149, 254);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,388 , 150, 407);&lt;br /&gt;
  //Pack 4&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(180, 234 , 310, 386);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(181, 254, 309, 254);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(180,388, 310, 407);&lt;br /&gt;
  //Fill Text&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Set_Text_Mode(1);&lt;br /&gt;
  //mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_Size(3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,24,320);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,25,320);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,26,320);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  //mylcd.Set_Text_Mode(1);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*0); &lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; x04 (-)       x20 (-)    &amp;quot;, 4, 30+16*1);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 1 -.---V      1 -.---V  &amp;quot;, 4, 32+16*2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 2 -.---V      2 -.---V  &amp;quot;, 4, 32+16*3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 3 -.---V      3 -.---V  &amp;quot;, 4, 32+16*4);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 4 -.---V      4 -.---V   &amp;quot;, 4, 32+16*5);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 5 -.---V      5 -.---V   &amp;quot;, 4, 32+16*6);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 6 -.---V      6 -.---V   &amp;quot;, 4, 32+16*7);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 7 -.---V      7 -.---V   &amp;quot;, 4, 32+16*8);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 8 -.---V      8 -.---V   &amp;quot;, 4, 32+16*9);&lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;     (+) --C      (+) --C &amp;quot;, 4, 38+16*10);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*11);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*12); &lt;br /&gt;
  //mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; x06 (-)       x22 (-)    &amp;quot;, 4, 30+16*13);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 1 -.---V      1 -.---V   &amp;quot;, 4, 32+16*14);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 2 -.---V      2 -.---V   &amp;quot;, 4, 32+16*15);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 3 -.---V      3 -.---V   &amp;quot;, 4, 32+16*16);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 4 -.---V      4 -.---V   &amp;quot;, 4, 32+16*17);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 5 -.---V      5 -.---V   &amp;quot;, 4, 32+16*18);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 6 -.---V      6 -.---V   &amp;quot;, 4, 32+16*19);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 7 -.---V      7 -.---V   &amp;quot;, 4, 32+16*20);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 8 -.---V      8 -.---V   &amp;quot;, 4, 32+16*21);&lt;br /&gt;
  //mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;     (+) --C      (+) --C &amp;quot;, 4, 38+16*22);&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*23);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*24);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*25);  &lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*26);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(void)&lt;br /&gt;
{&lt;br /&gt;
//  float voltage_[5][8]={{1.001,2.001,3.001,4.001,5.001,6.001,7.001,8.001},{1.002,2.002,3.002,4.002,5.002,6.002,7.002,8.002},{1.003,2.003,3.003,4.003,5.003,6.003,7.003,8.003},{1.004,2.004,3.004,4.004,5.004,6.004,7.004,8.004},{1.005,2.005,3.005,4.005,5.005,6.005,7.005,8.005}}; &lt;br /&gt;
  long st, fn;&lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=64+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=256+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=40;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=208;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=28</id>
		<title>CAN bus battery monitor with 3.5&quot; TFT Touch screen on Arudino MEGA2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=28"/>
		<updated>2020-11-04T06:12:05Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */ Added outlines of packs, decorated, refreshed look, place holders for max temp once implemented&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
Only Displays Packs 0-3. Does not autodetect modules. Snake Game easter egg not yet inmplemented&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;quot;mcp_can.h&amp;quot;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS 4     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS 8     //Hazardous to modify&lt;br /&gt;
#define REFRESH 1000   //Refresh rate display&lt;br /&gt;
#define ALARM 3.660    //Alarm threshold&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
#define GREY    0x0821&lt;br /&gt;
#define BACKGRD 0x2965&lt;br /&gt;
&lt;br /&gt;
//RED 1111 1000 0000 0000&lt;br /&gt;
//BLU 0000 0000 0001 1111&lt;br /&gt;
//GRE 0000 0111 1110 0000&lt;br /&gt;
//GRY 0000 1000 0010 0001 = 0x0821&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
boolean ledON = 1;&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
&lt;br /&gt;
unsigned char bufA[10];&lt;br /&gt;
unsigned char buf0[10];&lt;br /&gt;
unsigned char buf3[10];&lt;br /&gt;
unsigned char buf5[10];&lt;br /&gt;
unsigned char buf20[10];&lt;br /&gt;
unsigned char buf21[10];&lt;br /&gt;
unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  //mylcd.Fill_Screen(BLACK);&lt;br /&gt;
  //mylcd.Set_Text_Mode(0);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf3[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      else if (msgID == 0x00000500)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf5[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          bufA[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf0[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][7] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][6] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][5] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
              buf20[i] = buf[i];&lt;br /&gt;
          } &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][4] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][3] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][2] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf21[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][1] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][0] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf22[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)   //KILLER LINE&lt;br /&gt;
              //digitalWrite(49,1);&lt;br /&gt;
              buzzer=HIGH;&lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
&lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode=1)&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    //display 1 times string&lt;br /&gt;
  mylcd.Fill_Screen(BACKGRD);&lt;br /&gt;
  mylcd.Set_Draw_color(32,0,255);&lt;br /&gt;
  mylcd.Fill_Rectangle(0, 0, mylcd.Get_Display_Width()-1, 26);&lt;br /&gt;
  //Draw Packs&lt;br /&gt;
  //Pack 1&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,42 , 150, 191);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(11, 62, 149, 62);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,193 , 150, 214);&lt;br /&gt;
  //Pack 2&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(180,42 , 310, 191);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(181, 62, 309, 62);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(180,193, 310, 214);&lt;br /&gt;
  //Pack 3&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,234 , 150, 386);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(11, 254, 149, 254);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(10,388 , 150, 407);&lt;br /&gt;
  //Pack 4&lt;br /&gt;
  mylcd.Set_Draw_color(0,0,0);&lt;br /&gt;
  mylcd.Fill_Rectangle(180, 234 , 310, 386);&lt;br /&gt;
  mylcd.Set_Draw_color(WHITE);&lt;br /&gt;
  mylcd.Draw_Line(181, 254, 309, 254);&lt;br /&gt;
  mylcd.Set_Draw_color(RED);&lt;br /&gt;
  mylcd.Fill_Rectangle(180,388, 310, 407);&lt;br /&gt;
  //Fill Text&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Set_Text_Mode(1);&lt;br /&gt;
  //mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_Size(3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,24,320);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,25,320);&lt;br /&gt;
  //mylcd.Draw_Fast_HLine(0,26,320);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  //mylcd.Set_Text_Mode(1);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*0); &lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; x04 (-)       x20 (-)    &amp;quot;, 4, 30+16*1);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 1 -.---V      1 -.---V  &amp;quot;, 4, 32+16*2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 2 -.---V      2 -.---V  &amp;quot;, 4, 32+16*3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 3 -.---V      3 -.---V  &amp;quot;, 4, 32+16*4);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 4 -.---V      4 -.---V   &amp;quot;, 4, 32+16*5);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 5 -.---V      5 -.---V   &amp;quot;, 4, 32+16*6);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 6 -.---V      6 -.---V   &amp;quot;, 4, 32+16*7);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 7 -.---V      7 -.---V   &amp;quot;, 4, 32+16*8);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 8 -.---V      8 -.---V   &amp;quot;, 4, 32+16*9);&lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;     (+) --C      (+) --C &amp;quot;, 4, 38+16*10);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*11);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*12); &lt;br /&gt;
  //mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; x06 (-)       x22 (-)    &amp;quot;, 4, 30+16*13);&lt;br /&gt;
  //mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 1 -.---V      1 -.---V   &amp;quot;, 4, 32+16*14);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 2 -.---V      2 -.---V   &amp;quot;, 4, 32+16*15);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 3 -.---V      3 -.---V   &amp;quot;, 4, 32+16*16);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 4 -.---V      4 -.---V   &amp;quot;, 4, 32+16*17);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 5 -.---V      5 -.---V   &amp;quot;, 4, 32+16*18);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 6 -.---V      6 -.---V   &amp;quot;, 4, 32+16*19);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 7 -.---V      7 -.---V   &amp;quot;, 4, 32+16*20);&lt;br /&gt;
  mylcd.Print_String(&amp;quot; 8 -.---V      8 -.---V   &amp;quot;, 4, 32+16*21);&lt;br /&gt;
  //mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;     (+) --C      (+) --C &amp;quot;, 4, 38+16*22);&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*23);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*24);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*25);  &lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*26);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Caleb Box and Timothy Legg&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(void)&lt;br /&gt;
{&lt;br /&gt;
//  float voltage_[5][8]={{1.001,2.001,3.001,4.001,5.001,6.001,7.001,8.001},{1.002,2.002,3.002,4.002,5.002,6.002,7.002,8.002},{1.003,2.003,3.003,4.003,5.003,6.003,7.003,8.003},{1.004,2.004,3.004,4.004,5.004,6.004,7.004,8.004},{1.005,2.005,3.005,4.005,5.005,6.005,7.005,8.005}}; &lt;br /&gt;
  long st, fn;&lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=32+16*2+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=32+16*3+(16*c)+16*11;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=4+12*3;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=4+12*7 + 120;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600 || voltage[p][c] &amp;lt; 3.200) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645 || voltage[p][c] &amp;lt; 3.150) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.900 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(GREY);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=27</id>
		<title>CAN bus battery monitor with 3.5&quot; TFT Touch screen on Arudino MEGA2560</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=CAN_bus_battery_monitor_with_3.5%22_TFT_Touch_screen_on_Arudino_MEGA2560&amp;diff=27"/>
		<updated>2020-11-04T01:16:18Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: /* Code */  Fixed buzzer issue, updated text on screen to change color depending on cell voltage&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Synopsis==&lt;br /&gt;
==Notes==&lt;br /&gt;
Only Displays Packs 0-3. Does not autodetect modules. Snake Game easter egg not yet inmplemented&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
#define ARDUINO_MEGA2560&lt;br /&gt;
//Arduino MEGA 2560&lt;br /&gt;
//MCP2515&lt;br /&gt;
////Pin 52 SPI clock&lt;br /&gt;
////Pin 50 MISO&lt;br /&gt;
////Pin 51 MOSI&lt;br /&gt;
////Pin 53 Cable Select&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;quot;mcp_can.h&amp;quot;&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
&lt;br /&gt;
//Software constants&lt;br /&gt;
#define NUMPACKS 5     //Number of packs installed on line.  Must edit knownID[] array&lt;br /&gt;
#define NUMCELLS 8     //Hazardous to modify&lt;br /&gt;
#define REFRESH 1000   //Refresh rate display&lt;br /&gt;
#define ALARM 3.655    //Alarm threshold&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
#define ORANGE  0xFC00&lt;br /&gt;
&lt;br /&gt;
//RED 1111 1000 0000 0000&lt;br /&gt;
//BLU 0000 0000 0001 1111&lt;br /&gt;
//GRE 0000 0111 1110 0000&lt;br /&gt;
//GRY 0000 1000 0010 0001 = 0x0821&lt;br /&gt;
&lt;br /&gt;
//Globals&lt;br /&gt;
bool buzzer = HIGH;&lt;br /&gt;
#ifdef ARDUINO_MEGA2560&lt;br /&gt;
const int spiCSPin = 53;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
boolean ledON = 1;&lt;br /&gt;
float voltage[NUMPACKS][NUMCELLS];&lt;br /&gt;
float sum[NUMPACKS];&lt;br /&gt;
long knownID[NUMPACKS] = {0x00000021, 0x00000004, 0x00000020, 0x00000006, 0x00000022};&lt;br /&gt;
long packID;&lt;br /&gt;
int slot;&lt;br /&gt;
int c= 0;&lt;br /&gt;
int p= 0;&lt;br /&gt;
float Pack = 0.0;&lt;br /&gt;
&lt;br /&gt;
unsigned char bufA[10];&lt;br /&gt;
unsigned char buf0[10];&lt;br /&gt;
unsigned char buf3[10];&lt;br /&gt;
unsigned char buf5[10];&lt;br /&gt;
unsigned char buf20[10];&lt;br /&gt;
unsigned char buf21[10];&lt;br /&gt;
unsigned char buf22[10];&lt;br /&gt;
&lt;br /&gt;
unsigned long time;&lt;br /&gt;
unsigned long TriggerTime = 0;&lt;br /&gt;
unsigned long unknownId = 0;&lt;br /&gt;
int count=0;&lt;br /&gt;
&lt;br /&gt;
MCP_CAN CAN(spiCSPin);&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
&lt;br /&gt;
  //Graphics&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  mylcd.Fill_Screen(BLACK);&lt;br /&gt;
   mylcd.Set_Text_Mode(0);&lt;br /&gt;
  BuildScreen(0);&lt;br /&gt;
&lt;br /&gt;
  //Pin 49 voltage alarm&lt;br /&gt;
  pinMode(49, OUTPUT);&lt;br /&gt;
  //Initialize against undefined values&lt;br /&gt;
  for(int i=0;i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
  {&lt;br /&gt;
    for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
    {&lt;br /&gt;
      voltage[i][j]=0.0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  while (CAN_OK != CAN.begin(CAN_125KBPS,MCP_8MHz))&lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;CAN BUS Init Failed, waiting for hardware...&amp;quot;);&lt;br /&gt;
    delay(100);&lt;br /&gt;
  }&lt;br /&gt;
  Serial.println(&amp;quot;CAN BUS  Init OK!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
  long msgID = 0x00000FFF;&lt;br /&gt;
  bool skip = LOW;&lt;br /&gt;
  unsigned char len = 0;&lt;br /&gt;
  unsigned char buf[10];&lt;br /&gt;
  unsigned long canId = 0x00000000;&lt;br /&gt;
&lt;br /&gt;
  if(CAN_MSGAVAIL == CAN.checkReceive())&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    CAN.readMsgBuf(&amp;amp;len, buf);&lt;br /&gt;
    canId = CAN.getCanId();&lt;br /&gt;
    if (canId &amp;amp; 0xFFFFF000 != 0x08010000)&lt;br /&gt;
    {&lt;br /&gt;
      Serial.println(&amp;quot;Unsupported device attached!  Correct and restart monitor.&amp;quot;);&lt;br /&gt;
      Serial.print(&amp;quot;Device: 0x&amp;quot;);&lt;br /&gt;
      Serial.print(canId &amp;amp; 0xFFFFF000,HEX);&lt;br /&gt;
      Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
      //Sound alarm&lt;br /&gt;
      digitalWrite(8,1);&lt;br /&gt;
      while(1){}&lt;br /&gt;
    }    &lt;br /&gt;
    //detect if pack is registered&lt;br /&gt;
    packID = canId &amp;amp; 0x000000FF;&lt;br /&gt;
    slot = 0xFF;&lt;br /&gt;
    for(int i = 0; i&amp;lt;NUMPACKS ; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if(knownID[i]==packID)&lt;br /&gt;
      {&lt;br /&gt;
        slot=i;&lt;br /&gt;
      }&lt;br /&gt;
      if(i==NUMPACKS-1 &amp;amp;&amp;amp; slot==0xFF)&lt;br /&gt;
      {&lt;br /&gt;
        Serial.println(&amp;quot;Unregistered Device attached!  Skipping!&amp;quot;);&lt;br /&gt;
        Serial.print(&amp;quot;  Device : 0x&amp;quot;);&lt;br /&gt;
        Serial.print(packID,HEX);&lt;br /&gt;
        Serial.println(&amp;quot;.&amp;quot;);&lt;br /&gt;
        skip = HIGH;    &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    //If pack is registered, collect it's data into local storage.&lt;br /&gt;
    if(!skip)&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
      msgID = canId &amp;amp; 0x00000F00;&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      if (msgID == 0x00000300)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf3[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 3&lt;br /&gt;
      else if (msgID == 0x00000500)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf5[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message A&lt;br /&gt;
      else if (msgID == 0x00000A00)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          bufA[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 0&lt;br /&gt;
      else if (msgID == 0x00000000)&lt;br /&gt;
      {&lt;br /&gt;
        for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
        {&lt;br /&gt;
          buf0[i] = buf[i];&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      //Interpret message 2&lt;br /&gt;
      else if (msgID == 0x00000200)&lt;br /&gt;
      {&lt;br /&gt;
        if (buf[0] == 0)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][7] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][6] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][5] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
              buf20[i] = buf[i];&lt;br /&gt;
          } &lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 1)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][4] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][3] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[6] * 256 + buf[5];&lt;br /&gt;
          voltage[slot][2] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf21[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        if (buf[0] == 2)&lt;br /&gt;
        {&lt;br /&gt;
          unsigned int Cell  = buf[2] * 256 + buf[1];&lt;br /&gt;
          voltage[slot][1] = Cell / 1000.0;&lt;br /&gt;
          Cell  = buf[4] * 256 + buf[3];&lt;br /&gt;
          voltage[slot][0] = Cell / 1000.0;&lt;br /&gt;
&lt;br /&gt;
          for(int i = 0; i&amp;lt;len; i++)&lt;br /&gt;
          {&lt;br /&gt;
            buf22[i] = buf[i];&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else &lt;br /&gt;
      {&lt;br /&gt;
        unknownId = canId;&lt;br /&gt;
        Serial.println(&amp;quot;Unexpected Message type detected!&amp;quot;);&lt;br /&gt;
        Serial.println(canId &amp;amp; 0x00000F00, HEX);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Run every REFRESHms&lt;br /&gt;
      time = millis();&lt;br /&gt;
      if (time &amp;gt;= TriggerTime)&lt;br /&gt;
      {&lt;br /&gt;
&lt;br /&gt;
        //Detect for alarm condition&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          for(int j=0;j&amp;lt;NUMCELLS;j++)&lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            if(voltage[i][j]&amp;gt;=ALARM)   //KILLER LINE&lt;br /&gt;
              //digitalWrite(49,1);&lt;br /&gt;
              buzzer=HIGH;&lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
              &lt;br /&gt;
          }            &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        //Execute alarm condition&lt;br /&gt;
        if(buzzer)&lt;br /&gt;
          digitalWrite(49,1);&lt;br /&gt;
        else&lt;br /&gt;
          digitalWrite(49,0);        &lt;br /&gt;
        TriggerTime = TriggerTime + REFRESH;&lt;br /&gt;
        Pack=0.0;&lt;br /&gt;
&lt;br /&gt;
        //Dump cell voltages to CSV&lt;br /&gt;
        for(int i=0; i&amp;lt;NUMPACKS;i++)&lt;br /&gt;
        {&lt;br /&gt;
          Pack=0.0;&lt;br /&gt;
          for(int j=0; j&amp;lt;NUMCELLS ; j++) &lt;br /&gt;
          {&lt;br /&gt;
&lt;br /&gt;
            Serial.print(voltage[i][j],3);&lt;br /&gt;
            Serial.print(&amp;quot;,&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            Pack += voltage[i][j];&lt;br /&gt;
&lt;br /&gt;
          }&lt;br /&gt;
          Serial.print(Pack,3);&lt;br /&gt;
          if(NUMPACKS-1!=i)&lt;br /&gt;
            Serial.print(',');&lt;br /&gt;
          else&lt;br /&gt;
            Serial.println();     &lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if(unknownId != 0)&lt;br /&gt;
        {&lt;br /&gt;
          Serial.print(&amp;quot;Unknown Message: &amp;quot;);&lt;br /&gt;
          Serial.print(unknownId, HEX);&lt;br /&gt;
          Serial.println();&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    else skip=LOW;    &lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    UpdateScreen();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void BuildScreen(int ScreenMode)&lt;br /&gt;
{&lt;br /&gt;
  //Home Screen&lt;br /&gt;
  if(ScreenMode=1)&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    //display 1 times string&lt;br /&gt;
  mylcd.Fill_Screen(0x0000);&lt;br /&gt;
  mylcd.Set_Text_colour(CYAN);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_Size(3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 30, 0);&lt;br /&gt;
  mylcd.Draw_Fast_HLine(0,24,320);&lt;br /&gt;
  mylcd.Draw_Fast_HLine(0,25,320);&lt;br /&gt;
  mylcd.Draw_Fast_HLine(0,26,320);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*0); &lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*1);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   1 = -.--- 1 = -.---    &amp;quot;, 4, 32+16*3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   2 = -.--- 2 = -.---    &amp;quot;, 4, 32+16*4);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   3 = -.--- 3 = -.---    &amp;quot;, 4, 32+16*5);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   4 = -.--- 4 = -.---    &amp;quot;, 4, 32+16*6);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   5 = -.--- 5 = -.---    &amp;quot;, 4, 32+16*7);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   6 = -.--- 6 = -.---    &amp;quot;, 4, 32+16*8);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   7 = -.--- 7 = -.---    &amp;quot;, 4, 32+16*9);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   8 = -.--- 8 = -.---    &amp;quot;, 4, 32+16*10);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*11);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   1 = -.--- 1 = -.---    &amp;quot;, 4, 32+16*12);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   2 = -.--- 2 = -.---    &amp;quot;, 4, 32+16*13);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   3 = -.--- 3 = -.---    &amp;quot;, 4, 32+16*14);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   4 = -.--- 4 = -.---    &amp;quot;, 4, 32+16*15);  &lt;br /&gt;
  mylcd.Print_String(&amp;quot;   5 = -.--- 5 = -.---    &amp;quot;, 4, 32+16*16);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   6 = -.--- 6 = -.---    &amp;quot;, 4, 32+16*17);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   7 = -.--- 7 = -.---    &amp;quot;, 4, 32+16*18);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;   8 = -.--- 8 = -.---    &amp;quot;, 4, 32+16*19);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;                          &amp;quot;, 4, 32+16*20);  &lt;br /&gt;
  mylcd.Print_String(&amp;quot;xxxxxxxxxxxxxxxxxxxxxxxxxx&amp;quot;, 4, 32+16*21);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Cell1 = 3.78|Cell2 = 3.321&amp;quot;, 4, 32+16*22);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Cell1 = 3.33|Cell2 = 3.321&amp;quot;, 4, 32+16*23);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Cell1 = 3.78|Cell2 = 3.321&amp;quot;, 4, 32+16*24);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Cell1 = 3.33|Cell2 = 3.321&amp;quot;, 4, 32+16*24);  &lt;br /&gt;
  mylcd.Print_String(&amp;quot;xxxxxxxxxxxxxxxxxxxxxxxxxx&amp;quot;, 4, 32+16*25);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;xxxxxxxxxxxxxxxxxxxxxxxxxx&amp;quot;, 4, 32+16*26);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;xxxxxxxxxxxxxxxxxxxxxxxxxx&amp;quot;, 4, 32+16*27);&lt;br /&gt;
  }&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void UpdateScreen(void)&lt;br /&gt;
{&lt;br /&gt;
//  float voltage_[5][8]={{1.001,2.001,3.001,4.001,5.001,6.001,7.001,8.001},{1.002,2.002,3.002,4.002,5.002,6.002,7.002,8.002},{1.003,2.003,3.003,4.003,5.003,6.003,7.003,8.003},{1.004,2.004,3.004,4.004,5.004,6.004,7.004,8.004},{1.005,2.005,3.005,4.005,5.005,6.005,7.005,8.005}}; &lt;br /&gt;
  long st, fn;&lt;br /&gt;
  int xc, yc;&lt;br /&gt;
  if(p==0 || p==1)&lt;br /&gt;
  {&lt;br /&gt;
    yc=32+16*3+(16*c);&lt;br /&gt;
  }&lt;br /&gt;
  if(p==2 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    yc=32+16*3+(16*c)+16*9;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==0 || p==2)&lt;br /&gt;
  {&lt;br /&gt;
    xc=4+12*7;&lt;br /&gt;
  }&lt;br /&gt;
  if(p==1 || p==3)&lt;br /&gt;
  {&lt;br /&gt;
    xc=4+12*7 + 120;&lt;br /&gt;
  }&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  if(voltage[p][c]&amp;lt; 2.200 || voltage[p][c] &amp;gt; 3.650) mylcd.Set_Text_colour(RED);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.600) mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  if(voltage[p][c]&amp;gt; 3.645) mylcd.Set_Text_colour(ORANGE);&lt;br /&gt;
  if(voltage[p][c]&amp;lt;= 0.0001) mylcd.Set_Text_colour(0x0821);&lt;br /&gt;
&lt;br /&gt;
  if(p!=4) mylcd.Print_Number_Float(voltage[p][c], 3, xc,yc, '.', 0, ' ');&lt;br /&gt;
&lt;br /&gt;
  if(c&amp;lt;NUMCELLS){c++;}&lt;br /&gt;
  if(c==NUMCELLS){p++;c=0;}&lt;br /&gt;
  if(p==NUMPACKS){p=0;}&lt;br /&gt;
  buzzer=LOW;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=LCD_demo&amp;diff=20</id>
		<title>LCD demo</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=LCD_demo&amp;diff=20"/>
		<updated>2020-11-02T21:09:24Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
/***********************************************************************************&lt;br /&gt;
*This program is a demo of displaying string&lt;br /&gt;
*This demo was made for LCD modules with 8bit or 16bit data port.&lt;br /&gt;
*This program requires the the LCDKIWI library.&lt;br /&gt;
&lt;br /&gt;
* File                : display_string.ino&lt;br /&gt;
* Hardware Environment: Arduino UNO&amp;amp;Mega2560&lt;br /&gt;
* Build Environment   : Arduino&lt;br /&gt;
&lt;br /&gt;
*Set the pins to the correct ones for your development shield or breakout board.&lt;br /&gt;
*This demo use the BREAKOUT BOARD only and use these 8bit data lines to the LCD,&lt;br /&gt;
*pin usage as follow:&lt;br /&gt;
*                  LCD_CS  LCD_CD  LCD_WR  LCD_RD  LCD_RST  SD_SS  SD_DI  SD_DO  SD_SCK &lt;br /&gt;
*     Arduino Uno    A3      A2      A1      A0      A4      10     11     12      13                            &lt;br /&gt;
*Arduino Mega2560    A3      A2      A1      A0      A4      10     11     12      13                           &lt;br /&gt;
&lt;br /&gt;
*                  LCD_D0  LCD_D1  LCD_D2  LCD_D3  LCD_D4  LCD_D5  LCD_D6  LCD_D7  &lt;br /&gt;
*     Arduino Uno    8       9       2       3       4       5       6       7&lt;br /&gt;
*Arduino Mega2560    8       9       2       3       4       5       6       7 &lt;br /&gt;
&lt;br /&gt;
*Remember to set the pins to suit your display module!&lt;br /&gt;
*&lt;br /&gt;
* @attention&lt;br /&gt;
*&lt;br /&gt;
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS&lt;br /&gt;
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE&lt;br /&gt;
* TIME. AS A RESULT, QD electronic SHALL NOT BE HELD LIABLE FOR ANY&lt;br /&gt;
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING&lt;br /&gt;
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE &lt;br /&gt;
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.&lt;br /&gt;
**********************************************************************************/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define  BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
&lt;br /&gt;
void setup() &lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(9600);&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  mylcd.Fill_Screen(BLACK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() &lt;br /&gt;
{&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  //display 1 times string&lt;br /&gt;
  mylcd.Fill_Screen(0x0000);&lt;br /&gt;
  mylcd.Set_Text_colour(RED);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_Size(3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 0, 0);&lt;br /&gt;
  //mylcd.Print_Number_Float(01234.56789, 2, 0, 8, '.', 0, ' ');  &lt;br /&gt;
  //mylcd.Print_Number_Int(0xDEADBEF, 0, 16, 0, ' ',16);&lt;br /&gt;
  //mylcd.Print_String(&amp;quot;DEADBEF&amp;quot;, 0, 16);&lt;br /&gt;
&lt;br /&gt;
  //display 2 times string&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Made by Caleb\nand Tim&amp;quot;, 0, 40);&lt;br /&gt;
  //mylcd.Print_Number_Float(01234.56789, 2, 0, 56, '.', 0, ' ');  &lt;br /&gt;
  //mylcd.Print_Number_Int(0xDEADBEF, 0, 72, 0, ' ',16);&lt;br /&gt;
  //mylcd.Print_String(&amp;quot;DEADBEEF&amp;quot;, 0, 72);&lt;br /&gt;
&lt;br /&gt;
  //display 3 times string&lt;br /&gt;
  mylcd.Set_Text_colour(BLUE);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery 1&amp;quot;, 0, 100);&lt;br /&gt;
  //mylcd.Print_Number_Float(01234.56789, 2, 0, 128, '.', 0, ' ');  &lt;br /&gt;
  //mylcd.Print_Number_Int(0xDEADBEF, 0, 152, 0, ' ',16);&lt;br /&gt;
 // mylcd.Print_String(&amp;quot;DEADBEEF&amp;quot;, 0, 152);&lt;br /&gt;
&lt;br /&gt;
  //display 4 times string&lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery 2&amp;quot;, 0, 140);&lt;br /&gt;
&lt;br /&gt;
  //display 5 times string&lt;br /&gt;
  mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery 3&amp;quot;, 0, 180);&lt;br /&gt;
&lt;br /&gt;
  //display 6 times string&lt;br /&gt;
  mylcd.Set_Text_colour(RED);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery 4&amp;quot;, 0, 220);&lt;br /&gt;
&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=LCD_demo&amp;diff=18</id>
		<title>LCD demo</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=LCD_demo&amp;diff=18"/>
		<updated>2020-11-02T20:26:43Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line='line'&amp;gt;&lt;br /&gt;
/***********************************************************************************&lt;br /&gt;
*This program is a demo of displaying string&lt;br /&gt;
*This demo was made for LCD modules with 8bit or 16bit data port.&lt;br /&gt;
*This program requires the the LCDKIWI library.&lt;br /&gt;
&lt;br /&gt;
* File                : display_string.ino&lt;br /&gt;
* Hardware Environment: Arduino UNO&amp;amp;Mega2560&lt;br /&gt;
* Build Environment   : Arduino&lt;br /&gt;
&lt;br /&gt;
*Set the pins to the correct ones for your development shield or breakout board.&lt;br /&gt;
*This demo use the BREAKOUT BOARD only and use these 8bit data lines to the LCD,&lt;br /&gt;
*pin usage as follow:&lt;br /&gt;
*                  LCD_CS  LCD_CD  LCD_WR  LCD_RD  LCD_RST  SD_SS  SD_DI  SD_DO  SD_SCK &lt;br /&gt;
*     Arduino Uno    A3      A2      A1      A0      A4      10     11     12      13                            &lt;br /&gt;
*Arduino Mega2560    A3      A2      A1      A0      A4      10     11     12      13                           &lt;br /&gt;
&lt;br /&gt;
*                  LCD_D0  LCD_D1  LCD_D2  LCD_D3  LCD_D4  LCD_D5  LCD_D6  LCD_D7  &lt;br /&gt;
*     Arduino Uno    8       9       2       3       4       5       6       7&lt;br /&gt;
*Arduino Mega2560    8       9       2       3       4       5       6       7 &lt;br /&gt;
&lt;br /&gt;
*Remember to set the pins to suit your display module!&lt;br /&gt;
*&lt;br /&gt;
* @attention&lt;br /&gt;
*&lt;br /&gt;
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS&lt;br /&gt;
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE&lt;br /&gt;
* TIME. AS A RESULT, QD electronic SHALL NOT BE HELD LIABLE FOR ANY&lt;br /&gt;
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING&lt;br /&gt;
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE &lt;br /&gt;
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.&lt;br /&gt;
**********************************************************************************/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define  BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
&lt;br /&gt;
void setup() &lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(9600);&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  mylcd.Fill_Screen(BLACK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() &lt;br /&gt;
{&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  //display 1 times string&lt;br /&gt;
  mylcd.Fill_Screen(0x0000);&lt;br /&gt;
  mylcd.Set_Text_colour(RED);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_Size(3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 0, 0);&lt;br /&gt;
  //mylcd.Print_Number_Float(01234.56789, 2, 0, 8, '.', 0, ' ');  &lt;br /&gt;
  //mylcd.Print_Number_Int(0xDEADBEF, 0, 16, 0, ' ',16);&lt;br /&gt;
  //mylcd.Print_String(&amp;quot;DEADBEF&amp;quot;, 0, 16);&lt;br /&gt;
&lt;br /&gt;
  //display 2 times string&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Made by Caleb\nand Tim&amp;quot;, 0, 40);&lt;br /&gt;
  //mylcd.Print_Number_Float(01234.56789, 2, 0, 56, '.', 0, ' ');  &lt;br /&gt;
  //mylcd.Print_Number_Int(0xDEADBEF, 0, 72, 0, ' ',16);&lt;br /&gt;
  //mylcd.Print_String(&amp;quot;DEADBEEF&amp;quot;, 0, 72);&lt;br /&gt;
&lt;br /&gt;
  //display 3 times string&lt;br /&gt;
  mylcd.Set_Text_colour(BLUE);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery 1&amp;quot;, 0, 100);&lt;br /&gt;
  //mylcd.Print_Number_Float(01234.56789, 2, 0, 128, '.', 0, ' ');  &lt;br /&gt;
  //mylcd.Print_Number_Int(0xDEADBEF, 0, 152, 0, ' ',16);&lt;br /&gt;
 // mylcd.Print_String(&amp;quot;DEADBEEF&amp;quot;, 0, 152);&lt;br /&gt;
&lt;br /&gt;
  //display 4 times string&lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery 2&amp;quot;, 0, 140);&lt;br /&gt;
&lt;br /&gt;
  //display 5 times string&lt;br /&gt;
  mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery 3&amp;quot;, 0, 180);&lt;br /&gt;
&lt;br /&gt;
  //display 6 times string&lt;br /&gt;
  mylcd.Set_Text_colour(RED);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery 4&amp;quot;, 0, 220);&lt;br /&gt;
&lt;br /&gt;
  delay(3000);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=LCD_demo&amp;diff=17</id>
		<title>LCD demo</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=LCD_demo&amp;diff=17"/>
		<updated>2020-11-02T20:23:14Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: This page is a modified demo that came with the new LCD board.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/***********************************************************************************&lt;br /&gt;
*This program is a demo of displaying string&lt;br /&gt;
*This demo was made for LCD modules with 8bit or 16bit data port.&lt;br /&gt;
*This program requires the the LCDKIWI library.&lt;br /&gt;
&lt;br /&gt;
* File                : display_string.ino&lt;br /&gt;
* Hardware Environment: Arduino UNO&amp;amp;Mega2560&lt;br /&gt;
* Build Environment   : Arduino&lt;br /&gt;
&lt;br /&gt;
*Set the pins to the correct ones for your development shield or breakout board.&lt;br /&gt;
*This demo use the BREAKOUT BOARD only and use these 8bit data lines to the LCD,&lt;br /&gt;
*pin usage as follow:&lt;br /&gt;
*                  LCD_CS  LCD_CD  LCD_WR  LCD_RD  LCD_RST  SD_SS  SD_DI  SD_DO  SD_SCK &lt;br /&gt;
*     Arduino Uno    A3      A2      A1      A0      A4      10     11     12      13                            &lt;br /&gt;
*Arduino Mega2560    A3      A2      A1      A0      A4      10     11     12      13                           &lt;br /&gt;
&lt;br /&gt;
*                  LCD_D0  LCD_D1  LCD_D2  LCD_D3  LCD_D4  LCD_D5  LCD_D6  LCD_D7  &lt;br /&gt;
*     Arduino Uno    8       9       2       3       4       5       6       7&lt;br /&gt;
*Arduino Mega2560    8       9       2       3       4       5       6       7 &lt;br /&gt;
&lt;br /&gt;
*Remember to set the pins to suit your display module!&lt;br /&gt;
*&lt;br /&gt;
* @attention&lt;br /&gt;
*&lt;br /&gt;
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS&lt;br /&gt;
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE&lt;br /&gt;
* TIME. AS A RESULT, QD electronic SHALL NOT BE HELD LIABLE FOR ANY&lt;br /&gt;
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING&lt;br /&gt;
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE &lt;br /&gt;
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.&lt;br /&gt;
**********************************************************************************/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;LCDWIKI_GUI.h&amp;gt; //Core graphics library&lt;br /&gt;
#include &amp;lt;LCDWIKI_KBV.h&amp;gt; //Hardware-specific library&lt;br /&gt;
&lt;br /&gt;
//if the IC model is known or the modules is unreadable,you can use this constructed function&lt;br /&gt;
LCDWIKI_KBV mylcd(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset&lt;br /&gt;
//if the IC model is not known and the modules is readable,you can use this constructed function&lt;br /&gt;
//LCDWIKI_KBV mylcd(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset&lt;br /&gt;
&lt;br /&gt;
//define some colour values&lt;br /&gt;
#define  BLACK   0x0000&lt;br /&gt;
#define BLUE    0x001F&lt;br /&gt;
#define RED     0xF800&lt;br /&gt;
#define GREEN   0x07E0&lt;br /&gt;
#define CYAN    0x07FF&lt;br /&gt;
#define MAGENTA 0xF81F&lt;br /&gt;
#define YELLOW  0xFFE0&lt;br /&gt;
#define WHITE   0xFFFF&lt;br /&gt;
&lt;br /&gt;
void setup() &lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(9600);&lt;br /&gt;
  mylcd.Init_LCD();&lt;br /&gt;
  Serial.println(mylcd.Read_ID(), HEX);&lt;br /&gt;
  mylcd.Fill_Screen(BLACK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() &lt;br /&gt;
{&lt;br /&gt;
  mylcd.Set_Text_Mode(0);&lt;br /&gt;
  //display 1 times string&lt;br /&gt;
  mylcd.Fill_Screen(0x0000);&lt;br /&gt;
  mylcd.Set_Text_colour(RED);&lt;br /&gt;
  mylcd.Set_Text_Back_colour(BLACK);&lt;br /&gt;
  mylcd.Set_Text_Size(3);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery Monitor&amp;quot;, 0, 0);&lt;br /&gt;
  //mylcd.Print_Number_Float(01234.56789, 2, 0, 8, '.', 0, ' ');  &lt;br /&gt;
  //mylcd.Print_Number_Int(0xDEADBEF, 0, 16, 0, ' ',16);&lt;br /&gt;
  //mylcd.Print_String(&amp;quot;DEADBEF&amp;quot;, 0, 16);&lt;br /&gt;
&lt;br /&gt;
  //display 2 times string&lt;br /&gt;
  mylcd.Set_Text_colour(GREEN);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Made by Caleb\nand Tim&amp;quot;, 0, 40);&lt;br /&gt;
  //mylcd.Print_Number_Float(01234.56789, 2, 0, 56, '.', 0, ' ');  &lt;br /&gt;
  //mylcd.Print_Number_Int(0xDEADBEF, 0, 72, 0, ' ',16);&lt;br /&gt;
  //mylcd.Print_String(&amp;quot;DEADBEEF&amp;quot;, 0, 72);&lt;br /&gt;
&lt;br /&gt;
  //display 3 times string&lt;br /&gt;
  mylcd.Set_Text_colour(BLUE);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery 1&amp;quot;, 0, 100);&lt;br /&gt;
  //mylcd.Print_Number_Float(01234.56789, 2, 0, 128, '.', 0, ' ');  &lt;br /&gt;
  //mylcd.Print_Number_Int(0xDEADBEF, 0, 152, 0, ' ',16);&lt;br /&gt;
 // mylcd.Print_String(&amp;quot;DEADBEEF&amp;quot;, 0, 152);&lt;br /&gt;
&lt;br /&gt;
  //display 4 times string&lt;br /&gt;
  mylcd.Set_Text_colour(WHITE);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery 2&amp;quot;, 0, 140);&lt;br /&gt;
&lt;br /&gt;
  //display 5 times string&lt;br /&gt;
  mylcd.Set_Text_colour(YELLOW);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery 3&amp;quot;, 0, 180);&lt;br /&gt;
&lt;br /&gt;
  //display 6 times string&lt;br /&gt;
  mylcd.Set_Text_colour(RED);&lt;br /&gt;
  mylcd.Set_Text_Size(2);&lt;br /&gt;
  mylcd.Print_String(&amp;quot;Battery 4&amp;quot;, 0, 220);&lt;br /&gt;
&lt;br /&gt;
  delay(3000);&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
	<entry>
		<id>http://calebneedscollege.com/wiki/index.php?title=Arduino_Projects&amp;diff=16</id>
		<title>Arduino Projects</title>
		<link rel="alternate" type="text/html" href="http://calebneedscollege.com/wiki/index.php?title=Arduino_Projects&amp;diff=16"/>
		<updated>2020-11-02T20:22:36Z</updated>

		<summary type="html">&lt;p&gt;Falgsc-al: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Can bus battery monitor with OLED]]&lt;br /&gt;
&lt;br /&gt;
[[Can bus battery monitor]]&lt;br /&gt;
&lt;br /&gt;
[[OLED Display]]&lt;br /&gt;
&lt;br /&gt;
[[OLED Display SSD1306 i2c 128x64 demo]]&lt;br /&gt;
&lt;br /&gt;
[[LCD demo]]&lt;/div&gt;</summary>
		<author><name>Falgsc-al</name></author>
		
	</entry>
</feed>