* Please, don't change this Text, because most of Code is not mine!
* ==================================================================
* Modification of GreatScottLab's
* DIY Adjustable Constant Load (Current & Power)
* https://www.instructables.com/id/DIY-Adjustable-Constant-Load-Current-Power/
*
* I had some 5110 LCD's laying arround, so I adjusted original code for it
* added CPU Cooler with fan and thermo resistor for Temperature sensing
*/
#include
#include
#include
#include
#include
#include
#define clk 3
#define dt 2
#define sw 4
#define pwm 9
#define pwm_fan 10 // fan speed
#define fan 5 // fan power on/off
#define currentsense A3
#define voltagesense A1
#define tempsense A2 // thermo resistor (8kOhm, salvaged from Old Laptop Battery pack)
Adafruit_PCD8544 display = Adafruit_PCD8544(13, 12, 11, 8, 7);
#define LCDLight 6 // LCD background light connected to digital pin 6 on Arduino
const unsigned char PROGMEM splash[] ={0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x10,
0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x00, 0x10,
0x80, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x10,
0x80, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x10,
0x80, 0x00, 0x7f, 0x00, 0x00, 0x18, 0x00, 0x03, 0xfc, 0x00, 0x10,
0x80, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x02, 0x00, 0x00, 0x10,
0x80, 0x00, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x02, 0x00, 0x00, 0x10,
0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10,
0x80, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10,
0x80, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0};
const unsigned char PROGMEM highV[] ={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0f, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1e, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1e, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x78, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x78, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xf1, 0xe7, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xf3, 0xc7, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xe3, 0xc3, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xe3, 0x83, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc3, 0x81, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc7, 0x81, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x87, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x87, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f, 0x07, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f, 0x06, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1e, 0x0e, 0x10, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1e, 0x0c, 0x70, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3c, 0x0c, 0xe0, 0x1e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3c, 0x0f, 0xe0, 0x1e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x78, 0x1f, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x78, 0x1e, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xf0, 0x18, 0xc0, 0x07, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xf0, 0x10, 0xc0, 0x07, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0xe0, 0x00, 0xc0, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0xe0, 0x01, 0xc0, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0xc0, 0x01, 0xc0, 0x01, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0xc0, 0x01, 0x80, 0x01, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0x80, 0x07, 0xe0, 0x00, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x00, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0f, 0x00, 0x03, 0xc0, 0x00, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0f, 0x00, 0x01, 0x80, 0x00, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x00, 0x01, 0x80, 0x00, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned char PROGMEM low_bat[] ={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00,
0x00, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x00, 0x00, 0x18, 0x00, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x18, 0x00, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1f, 0xe0, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x00, 0x38, 0x00, 0x00, 0x18, 0x30, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x00, 0x78, 0x00, 0x00, 0x18, 0x30, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x18, 0x30, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x18, 0x30, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x18, 0x30, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x18, 0x30, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x18, 0x30, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x18, 0x30, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x18, 0x30, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x18, 0x30, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x18, 0x30, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x18, 0x30, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x1f, 0xe0, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x00, 0x18, 0x00, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x01, 0x80, 0x00, 0x00, 0x18, 0x00, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
0x03, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x00, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned char PROGMEM hot[] ={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x03, 0xbc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0xbc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0xbc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0xbc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0xbc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0xbc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x79, 0xbc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1e, 0x79, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x38, 0x78, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x70, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x71, 0xfc, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe3, 0xfe, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc7, 0xff, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xcf, 0xff, 0x8c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x8f, 0xff, 0x8c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x8f, 0xff, 0x8c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x8f, 0xff, 0x8c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x8f, 0xff, 0x8c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x8f, 0xff, 0x8c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xc7, 0xff, 0x9c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc7, 0xff, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc3, 0xfe, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe1, 0xfc, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3c, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1f, 0x8f, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned char PROGMEM arrow[] = {0x80,
0xc0,
0xe0,
0xf0,
0xe0,
0xc0,
0x80};
int screen = -1;
int arrowpos = 0;
int line = 7;
int tens = 0;
int ones = 0;
int dec1 = 0;
int dec2 = 0;
float power = 0;
float current = 0;
float curcurrent = 0;
float curpower = 0;
float curvoltage = 0;
float curcurrentraw = 0;
float zerocurrent;
float curvoltraw = 0;
int counter = 0;
float max_power=199.99;
float max_current=15.0;
float min_voltage = 3.0;
float max_voltage = 27.0;
unsigned long refStart;
int zerotmp=250;
int maxTemp=750;
int tempraw;
volatile boolean fan_state = false; // fan switched Off
int contrast = 60; // LCD contrast
/**
* Sensitivity of Current sensor
* 5A = 185.00
* 20A = 100.00
* 30A = 66.00;
*/
float cursense = 100.00; // at built Time I had only 5A Current Sensor
volatile boolean currentmode = false;
volatile boolean powermode = false;
volatile boolean TurnDetected = false;
volatile boolean up = false;
volatile boolean button = false;
float refV;
int timer = 1000; // mSec to refresh LCD
float tolerance = 1.0; // Tolerance for measure voltage against calibrated Multimeter
// Voltage divider schema
// try to use precision 1% tolerance resistors
//
//
// -> | Input Voltage
// [ ]
// [ ] RxUpper Resistor
// |
// |-- > to Arduino Analog
// |
// [ ] RxLower Resistor
// [ ]
// |
// GND
// all Values are in Ohm
// Input Voltage
float R1Upper = 10000.0; // resistance of upper resistor - see above Graphics
float R1Lower = 2000.0; // resistance of lower resistor - see above Graphics
float ratio1= R1Lower/(R1Upper+R1Lower);
const unsigned char PS_128 = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
float test=0;
ISR(PCINT2_vect) {
if (digitalRead(sw) == LOW) {
button = true;
}
}
void isr0 () {
TurnDetected = true;
up = (digitalRead(clk) == digitalRead(dt));
delay(20);
}
void setup() {
//Serial.begin(115200);
screen = -1;
pinMode(sw, INPUT_PULLUP);
pinMode(clk, INPUT);
pinMode(dt, INPUT);
pinMode(pwm, OUTPUT);
pinMode(currentsense, INPUT);
pinMode(LCDLight,OUTPUT);
pinMode(pwm_fan, OUTPUT); // fan speed
pinMode(tempsense, INPUT);// temperature sensor
pinMode(fan, OUTPUT); // fan switch
analogReference(DEFAULT);
digitalWrite(LCDLight,LOW);
digitalWrite(pwm, LOW);
ADCSRA &= ~PS_128;
ADCSRA |= (1 << ADPS1) | (1 << ADPS0);
PCICR |= 0b00000100;
PCMSK2 |= 0b00010000; // turn o PCINT20(D4)
attachInterrupt(0, isr0, RISING);
TCCR1A = 0;
TCCR1A = (1 << COM1A1) | (1 << WGM11);
TCCR1B = 0;
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);
ICR1 = 2047;
OCR1A = 0;
refV = readVcc();
//refV=1.1;
curvoltage = ((analogRead(voltagesense) * refV) / 1024.0)/ratio1/1000;
/** show splash screen */
display.begin();
display.setContrast(50);
display.clearDisplay();
display.drawBitmap(0,0,splash,84,48,1);
display.setTextSize(1);
display.setCursor(4,4);
display.print("ELECTRONIC");
display.setCursor(15,13);
display.print("LOAD");
display.setFont(&Org_01);
display.setCursor(30,41);
display.print("by MICKEY");
display.setTextSize(1);
display.display();
delay(3000); // show splash for 3 sec
display.clearDisplay();
zerocurrent=calibrate_sensor();
refStart = millis();
curvoltage = ((analogRead(voltagesense) * refV) / 1024.0)/ratio1/1000;
if(curvoltage > max_voltage) high_input();
}
void loop() {
/*int tempraw=analogRead(tempsense);
if(tempraw > 900){
//Serial.println(tempraw);
if(currentmode) currentmode=false;
if(powermode)powermode=false;
OCR1A = 0;
display.clearDisplay();
display.drawBitmap(0,0,hot,84,48,1);
display.display();
// stop();
}
*/
readTemp(); // read temperature
/*read Vcc Voltage each 5 sec*/
if (millis()-refStart > 5000){
refV=readVcc();
delay(20);
refStart=millis();
}
if (currentmode) {
// take 20 readings of Current
curcurrentraw=0;
for (int i = 0; i < 20; i++) {
curcurrentraw += analogRead(currentsense);
}
curcurrent = abs((((curcurrentraw/20) - zerocurrent) * (refV / 1023.00) / cursense));
if(curcurrent > max_current) {
stepDown();
}
if(curcurrent<0) curcurrent=0;
if (counter == timer) {
screen6();
counter = 0;
}
if (curcurrent < current) {
OCR1A++;
}
else {
if(OCR1A>0){
OCR1A = OCR1A - 1;
} else {
OCR1A=0;
}
}
OCR1A=constrain(OCR1A,0,2047);
counter++;
delayMicroseconds(100);
}
if (powermode) {
// take 20 readings of Current
curcurrentraw=0;
for (int i = 0; i < 20; i++) {
curcurrentraw += analogRead(currentsense);
}
curcurrent = abs((((curcurrentraw/20) - zerocurrent) * (refV / 1023.00) / cursense));
if(curcurrent > max_current){
stepDown();
}
curvoltage = ((analogRead(voltagesense) * refV) / 1023.0)/ratio1/1000;
curpower = curvoltage * curcurrent;
if (counter == timer) {
screen3();
counter = 0;
}
if (curpower < power) {
OCR1A++;
}
else {
if(OCR1A>0){
OCR1A = OCR1A - 1;
} else {
OCR1A=0;
}
}
OCR1A=constrain(OCR1A,0,2048);
counter++;
delayMicroseconds(100);
}
if (TurnDetected) {
delay(20);
switch (screen) {
case -1:
screen=0;
screen0();
break;
case 0:
switch (arrowpos) {
case 0:
screen0();
arrowpos=1;
break;
case 1:
screen0();
arrowpos =0;
break;
}
print_arrow();
break;
case 1:
switch (arrowpos) {
case 0:
if(!up){
screen1();
arrowpos=1;
} else {
screen1();
arrowpos=2;
}
break;
case 1:
if (!up) {
screen1();
arrowpos = 2;
} else {
screen1();
arrowpos = 0;
}
break;
case 2:
if (!up) {
screen1();
arrowpos = 0;
} else {
screen1();
arrowpos = 1;
}
break;
}
print_arrow();
break;
case 2:
if (!up) {
power = power + 0.25;
if(power > max_power) power = max_power;
screen2();
}
else {
power = power - 0.25;
if (power < 0) {
power = 0;
}
screen2();
}
display.display();
break;
case 3:
if (arrowpos==3) {
arrowpos = 2;
screen=1;
screen1();
}
break;
case 4:
switch (arrowpos) {
case 0:
if(!up){
screen4();
arrowpos=1;
} else {
screen4();
arrowpos=2;
}
break;
case 1:
if (!up) {
screen4();
arrowpos = 2;
} else {
screen4();
arrowpos = 0;
}
break;
case 2:
if (!up) {
screen4();
arrowpos = 0;
} else {
screen4();
arrowpos = 1;
}
break;
}
print_arrow();
break;
case 5:
if (!up) {
current = current + 0.25;
if (current > max_current) current=max_current;
screen5();
}
else {
current = current - 0.25;
if (current < 0) {
current = 0;
}
screen5();
}
display.display();
break;
}
TurnDetected = false;
}
if (button) {
button = false;
delay(200);
switch (screen) {
case -1:
screen=0;
screen0();
break;
case 0:
if (arrowpos == 0) {
screen = 1;
arrowpos=2;
screen1();
}
else {
arrowpos=2;
screen = 4;
screen4();
}
break;
case 1:
switch (arrowpos) {
case 0:
screen = 2;
screen2();
if(power <10.0){
display.setCursor(20, 25);
} else {
display.setCursor(6, 25);
}
break;
case 1:
if(power > 0){
powermode = true;
screen = 3;
screen3();
}
break;
case 2:
arrowpos = 0;
screen = 0;
screen0();
break;
}
break;
case 2:
screen = 1;
arrowpos=1;
screen1();
break;
case 3:
powermode = false;
OCR1A = 0;
counter = 0;
screen = 1;
screen1();
break;
case 4:
switch (arrowpos) {
case 0:
screen = 5;
screen5();
if(current <10.0){
display.setCursor(20, 25);
} else {
display.setCursor(6, 25);
}
break;
case 1:
if(current > 0){
currentmode = true;
screen = 6;
screen6();
}
break;
case 2:
arrowpos = 1;
screen = 0;
screen0();
break;
}
break;
case 5:
arrowpos=1;
screen = 4;
screen4();
break;
case 6:
currentmode = false;
OCR1A = 0;
screen = 4;
screen4();
break;
}
print_arrow();
button = false;
display.display();
}
}
void screen0() {
display.setFont();
display.clearDisplay();
display.setCursor(10, 10);
display.print("Power Mode");
display.setCursor(10, 30);
display.print("Current Mode");
display.display();
}
void screen1() {
display.clearDisplay();
display.setCursor(20, 5);
display.print("Power (W)");
if(power <10.0){
display.setCursor(20, 25);
} else {
display.setCursor(6, 25);
}
display.setFont(&FreeMonoBold12pt7b);
display.print(power);
display.setFont();
display.setCursor(10, 40);
display.print("Start");
display.setCursor(55, 40);
display.print("Back");
display.display();
}
void screen2() {
display.clearDisplay();
display.setCursor(20, 5);
display.print("Power (W)");
if(power <10.0){
display.setCursor(20, 25);
} else {
display.setCursor(6, 25);
}
display.setFont(&FreeMonoBold12pt7b);
display.print(power);
display.setFont();
display.setCursor(10, 40);
display.print("Button = SET");
display.display();
}
void screen3() {
display.clearDisplay();
display.print("Set PWR:");
display.print(power);
display.print("W");
display.setFont(&FreeMonoBold12pt7b);
if(curpower <10.0){
display.setCursor(20, 25);
} else {
display.setCursor(6, 25);
}
display.print(curpower);
display.setFont();
display.setCursor(30, 40);
//display.write((uint8_t)0);
display.print("STOP");
display.display();
}
void screen4() {
display.clearDisplay();
display.setCursor(10, 5);
display.print("Current (A)");
if(current <10.0){
display.setCursor(20, 25);
} else {
display.setCursor(6, 25);
}
display.setFont(&FreeMonoBold12pt7b);
display.print(current);
display.setFont();
display.setCursor(10, 40);
display.print("Start");
display.setCursor(55, 40);
display.print("Back");
display.display();
}
void screen5() {
display.clearDisplay();
display.setCursor(10, 5);
display.print("Current (A)");
if(current <10.0){
display.setCursor(20, 25);
} else {
display.setCursor(6, 25);
}
display.setFont(&FreeMonoBold12pt7b);
display.print(current);
display.setFont();
display.setCursor(10, 40);
display.print("Button = SET");
display.display();
}
void screen6() {
display.clearDisplay();
display.print("Set CUR:");
display.print(current);
display.print("A");
display.setFont(&FreeMonoBold12pt7b);
if(curcurrent <10.0){
display.setCursor(20, 25);
} else {
display.setCursor(6, 25);
}
display.print(curcurrent);
display.setFont();
display.setCursor(30, 40);
display.print("STOP");
display.display();
}
void print_arrow(){
switch (screen){
case 0:
switch (arrowpos){
case 0:
display.drawBitmap(0,10,arrow,5,7,1);
break;
case 1:
display.drawBitmap(0,30,arrow,5,7,1);
break;
}
break;
case 1:
switch (arrowpos){
case 0:
display.drawBitmap(0,20,arrow,5,7,1);
break;
case 1:
display.drawBitmap(0,40,arrow,5,7,1);
break;
case 2:
display.drawBitmap(50,40,arrow,5,7,1);
break;
}
break;
case 4:
switch (arrowpos){
case 0:
display.drawBitmap(0,20,arrow,5,7,1);
break;
case 1:
display.drawBitmap(0,40,arrow,5,7,1);
break;
case 2:
display.drawBitmap(50,40,arrow,5,7,1);
break;
}
break;
}
display.display();
}
long readVcc() {
long result;
// Read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(20); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = 1125300L / result; // Back-calculate AVcc in mV
return result;
}
int calibrate_sensor(){
uint16_t acc = 0;
for (int i = 0; i < 20; i++) {
acc += analogRead(currentsense);
}
int zero = acc / 20;
return zero;
}
void low_input(){
/* if input voltage is below defined value (minInV) show the picture,
* and stop the code
*/
OCR1A = 0;
analogWrite(pwm_fan,0);
display.clearDisplay();
display.drawBitmap(0,0,low_bat,84,48,1);
display.display();
stop();
}
void high_input(){
/* if input voltage is above defined value (maxInV) show the picture,
* and stop the code
*/
OCR1A = 0;
analogWrite(pwm_fan,0);
display.clearDisplay();
display.drawBitmap(0,0,highV,84,48,1);
display.display();
stop();
}
/** read temperature from sensor */
void readTemp(){
tempraw = analogRead(tempsense);
if(tempraw>maxTemp) tempraw=maxTemp;
Serial.println(tempraw);
if(tempraw > zerotmp && tempraw < maxTemp){
if(!fan_state) fan_on();
int temp=map(tempraw,zerotmp,maxTemp,0,640);
Serial.println(temp);
analogWrite(fan,temp);
} else if(tempraw < zerotmp){
if(fan_state){
analogWrite(fan,0); // set fan speed to 0
fan_off(); // switch fan power off
}
} else if (tempraw > maxTemp){
if (currentmode) currentmode=false;
if (powermode) powermode = false;
OCR1A = 0;
//fan_off();
display.clearDisplay();
display.drawBitmap(0,0,hot,84,48,1);
display.display();
stop();
}
}
/** switch Fan on */
void fan_on(){
digitalWrite(fan,HIGH);
fan_state = true;
}
/** switch Fan off */
void fan_off(){
digitalWrite(fan,LOW);
fan_state = false;
}
/** stop the execution */
void stop()
{
Serial.println(tempraw);
while(1);
}
void stepDown(){
OCR1A=OCR1A-5;
constrain(OCR1A,0,2047);
}