Update uno-stats-monitor/monitor_uno.ino
added an 8 x 8 LED matrix and IR receiver LED shows CPU load as a bar graph IR receiver reports key press events back through serial connection general code cleanup
This commit is contained in:
@@ -1,54 +1,136 @@
|
||||
/*
|
||||
* UNO Monitor Receiver (4-bit LCD Version)
|
||||
* kidacro@archamedis.net
|
||||
* Kidacro <kidacro@archamedis.net>
|
||||
*
|
||||
* Waits for input over serial connection and displays on LCD
|
||||
* Waits for input over serial connection and displays on LCD & LED
|
||||
* Receives IR events and reports them over serial connection to a daemon
|
||||
*
|
||||
* Input Schema:
|
||||
* Start char is: '#'
|
||||
* End char is: '@'
|
||||
* 2nd char denotes which line number to use
|
||||
* 2nd char denotes which line number/mode to use
|
||||
*
|
||||
* Example:
|
||||
* Line 1: #1Archamedis Status@
|
||||
* Line 2: #299% free / etc.@
|
||||
* LAVG 3: #324@
|
||||
*
|
||||
* Output Schema:
|
||||
* Multimedia Controls use single characters to denote which button was pressed
|
||||
* P power
|
||||
* M mute
|
||||
* m mode
|
||||
* p pause/play
|
||||
* b back
|
||||
* f forward
|
||||
* e eq
|
||||
* - vol down
|
||||
* + vol up
|
||||
* r return
|
||||
* u usb scan
|
||||
* 0 number 0
|
||||
* 1 number 1
|
||||
* 2 number 2
|
||||
* 3 number 3
|
||||
* 4 number 4
|
||||
* 5 number 5
|
||||
* 6 number 6
|
||||
* 7 number 7
|
||||
* 8 number 8
|
||||
* 9 number 9
|
||||
* R repeat
|
||||
* Z other button pressed
|
||||
*/
|
||||
|
||||
// include the library code:
|
||||
#include <LiquidCrystal.h>
|
||||
#include <LedControl.h>
|
||||
#include <IRremote.h>
|
||||
|
||||
// LCD Pinout:
|
||||
// LCD RS pin to digital pin 12
|
||||
// LCD Enable pin to digital pin 11
|
||||
// LCD D4 pin to digital pin 5
|
||||
// LCD D5 pin to digital pin 4
|
||||
// LCD D6 pin to digital pin 3
|
||||
// LCD D7 pin to digital pin 2
|
||||
// LCD R/W pin to ground
|
||||
// LCD VSS pin to ground
|
||||
// LCD VCC pin to 5V
|
||||
// 10K resistor:
|
||||
// ends to +5V and ground
|
||||
// wiper to LCD VO pin (pin 3)
|
||||
/* LCD Pinout:
|
||||
* LCD RS pin to digital pin 12
|
||||
* LCD Enable pin to digital pin 11
|
||||
* LCD D4 pin to digital pin 5
|
||||
* LCD D5 pin to digital pin 4
|
||||
* LCD D6 pin to digital pin 3
|
||||
* LCD D7 pin to digital pin 2
|
||||
* LCD R/W pin to ground
|
||||
* LCD VSS pin to ground
|
||||
* LCD VCC pin to 5V
|
||||
* 10K resistor:
|
||||
* ends to +5V and ground
|
||||
* wiper to LCD VO pin (pin 3)
|
||||
*/
|
||||
|
||||
/* LED Pinout:
|
||||
* LED DataIn(DIN) to digital pin 10
|
||||
* LED LOAD(CS) to digital pin 9
|
||||
* LED CLK to digital pin 8
|
||||
* LED VSS pin to 5V
|
||||
* LED GND to ground
|
||||
*/
|
||||
|
||||
/* IR Pinout
|
||||
* IR Signal to digital pin 13
|
||||
* IR VSS pin to 5V
|
||||
* IR GND to ground
|
||||
*/
|
||||
|
||||
// Variable Init
|
||||
// LCD vars
|
||||
// initialize the library by associating any needed LCD interface pin
|
||||
// with the arduino pin number it is connected to
|
||||
const int LCDRS = 12, LCDEN = 11, LCDD4 = 5, LCDD5 = 4, LCDD6 = 3, LCDD7 = 2;
|
||||
int LCDLength = 16;
|
||||
LiquidCrystal LCD(LCDRS, LCDEN, LCDD4, LCDD5, LCDD6, LCDD7);
|
||||
|
||||
// LED vars
|
||||
const int LEDIN = 10, LEDCS = 9, LEDCLK = 8;
|
||||
LedControl LEDlc=LedControl(LEDIN,LEDCLK,LEDCS,1);
|
||||
unsigned long LEDdelaytime1=5;
|
||||
unsigned long LEDdelaytime2=5;
|
||||
|
||||
// IR vars
|
||||
const int IRSIG = 13;
|
||||
IRrecv Irrecv(IRSIG);
|
||||
decode_results IRresults;
|
||||
|
||||
// Serial vars
|
||||
const byte numChars = 32;
|
||||
char receivedChars[numChars]; // an array to store the received data
|
||||
boolean newData = false;
|
||||
const byte SERnumChars = 32;
|
||||
char SERrecvChars[SERnumChars];
|
||||
boolean SERnewData = false;
|
||||
|
||||
// Debugging (serial console must be connected)
|
||||
bool DEBUG = 1;
|
||||
// Debugging
|
||||
boolean DEBUG = false;
|
||||
|
||||
void LcdL1(boolean wipe = false) {
|
||||
void LEDSetup(void)
|
||||
{
|
||||
/*
|
||||
The MAX72XX is in power-saving mode on startup,
|
||||
we have to do a wakeup call
|
||||
*/
|
||||
LEDlc.shutdown(0,false);
|
||||
|
||||
/* Set the brightness to medium values */
|
||||
LEDlc.setIntensity(0,8);
|
||||
|
||||
/* and clear the display */
|
||||
LEDlc.clearDisplay(0);
|
||||
}
|
||||
|
||||
void LcdSetup(void)
|
||||
{
|
||||
// set up the LCD's number of columns and rows:
|
||||
LCD.begin(LCDLength, 2);
|
||||
|
||||
// clear
|
||||
LCD.clear();
|
||||
}
|
||||
|
||||
void IRSetup(void)
|
||||
{
|
||||
// Start the receiver
|
||||
Irrecv.enableIRIn();
|
||||
}
|
||||
|
||||
void LcdL1(boolean wipe = false)
|
||||
{
|
||||
delay(10);
|
||||
LCD.setCursor(0, 0); // Define the cursor position as the 1st position of the 1st line
|
||||
|
||||
@@ -60,7 +142,8 @@ void LcdL1(boolean wipe = false) {
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void LcdL2(boolean wipe = false) {
|
||||
void LcdL2(boolean wipe = false)
|
||||
{
|
||||
delay(10);
|
||||
LCD.setCursor(0, 1); // Define the cursor position as the 1st position of the 2nd line
|
||||
|
||||
@@ -72,17 +155,8 @@ void LcdL2(boolean wipe = false) {
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void LcdCls(void) {
|
||||
delay(10);
|
||||
LCD.clear(); // The screen is empty
|
||||
LcdL1(); // the cursor position is zeroed
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void LcdSetup(void) {
|
||||
// set up the LCD's number of columns and rows:
|
||||
LCD.begin(LCDLength, 2);
|
||||
|
||||
void LcdIntro(void)
|
||||
{
|
||||
// Print a "waiting" message to the LCD.
|
||||
LcdL1();
|
||||
LCD.print("Starting Up...");
|
||||
@@ -90,14 +164,25 @@ void LcdSetup(void) {
|
||||
LCD.print("Waiting for data");
|
||||
}
|
||||
|
||||
/* returns starting position of text
|
||||
void LcdCenter(int mylen) {
|
||||
void LcdCls(void)
|
||||
{
|
||||
delay(10);
|
||||
LCD.clear(); // The screen is empty
|
||||
LcdL1(); // the cursor position is zeroed
|
||||
delay(10);
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: returns starting position of text or 0 for 1st position
|
||||
void LcdCenter(int mylen)
|
||||
{
|
||||
int mypos = 0;
|
||||
|
||||
return mypos;
|
||||
}*/
|
||||
|
||||
void LcdWrite(String mymessage) {
|
||||
void LcdWrite(String mymessage)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned int mylen = mymessage.length();
|
||||
|
||||
@@ -127,102 +212,192 @@ void LcdWrite(String mymessage) {
|
||||
}
|
||||
}
|
||||
|
||||
void LcdWriteExample() {
|
||||
LcdCls();
|
||||
|
||||
LcdL1();
|
||||
LcdWrite("Archamedis Stats");
|
||||
|
||||
delay(20);
|
||||
|
||||
LcdL1(true);
|
||||
LcdWrite("4.3ghz 89% 68C");
|
||||
|
||||
delay(20);
|
||||
|
||||
LcdL2();
|
||||
LcdWrite("Ryzen 9 5950x");
|
||||
}
|
||||
|
||||
void recvWithStartEndMarkers() {
|
||||
static boolean recvInProgress = false;
|
||||
static byte ndx = 0;
|
||||
char startMarker = '#';
|
||||
char endMarker = '@';
|
||||
char rc;
|
||||
|
||||
while (Serial.available() > 0 && newData == false) {
|
||||
rc = Serial.read();
|
||||
|
||||
if(recvInProgress == true) {
|
||||
if(rc != endMarker) {
|
||||
receivedChars[ndx] = rc;
|
||||
ndx++;
|
||||
if (ndx >= numChars) {
|
||||
ndx = numChars - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
receivedChars[ndx] = '\0'; // terminate the string
|
||||
recvInProgress = false;
|
||||
ndx = 0;
|
||||
newData = true;
|
||||
}
|
||||
}
|
||||
|
||||
else if(rc == startMarker) {
|
||||
recvInProgress = true;
|
||||
}
|
||||
void LedIntro() {
|
||||
for(int row=0;row<8;row++) {
|
||||
for(int col=0;col<8;col++) {
|
||||
delay(LEDdelaytime2);
|
||||
LEDlc.setLed(0,row,col,true);
|
||||
delay(LEDdelaytime2);
|
||||
for(int i=0;i<col;i++) {
|
||||
LEDlc.setLed(0,row,col,false);
|
||||
delay(LEDdelaytime2);
|
||||
LEDlc.setLed(0,row,col,true);
|
||||
delay(LEDdelaytime2);
|
||||
}
|
||||
}
|
||||
}
|
||||
LEDlc.clearDisplay(0);
|
||||
}
|
||||
|
||||
void showNewData() {
|
||||
if(newData == true) {
|
||||
// FIXME: this is armchair math
|
||||
// this needs to be dynamic and based on available rows
|
||||
void LedShowLoad(const char *load)
|
||||
{
|
||||
int myload = atoi(load);
|
||||
int segments = 0;
|
||||
|
||||
if(DEBUG) {
|
||||
Serial.print("My input load: ");
|
||||
Serial.println(load);
|
||||
Serial.print("My calculated load: ");
|
||||
Serial.println(myload);
|
||||
}
|
||||
|
||||
LEDlc.clearDisplay(0);
|
||||
|
||||
if(myload <= 10) segments = 1;
|
||||
else if(myload <= 20 && myload > 10) segments = 2;
|
||||
else if(myload <= 30 && myload > 20) segments = 3;
|
||||
else if(myload <= 50 && myload > 30) segments = 4;
|
||||
else if(myload <= 60 && myload > 50) segments = 5;
|
||||
else if(myload <= 70 && myload > 60) segments = 6;
|
||||
else if(myload <= 85 && myload > 70) segments = 7;
|
||||
else if(myload > 84) segments = 8;
|
||||
|
||||
// segments as rows
|
||||
for(int row=0;row<8;row++) {
|
||||
for(int col=0;col<segments;col++) {
|
||||
delay(LEDdelaytime2);
|
||||
LEDlc.setLed(0,row,col,true);
|
||||
delay(LEDdelaytime2);
|
||||
for(int i=0;i<col;i++) {
|
||||
LEDlc.setLed(0,row,col,false);
|
||||
delay(LEDdelaytime2);
|
||||
LEDlc.setLed(0,row,col,true);
|
||||
delay(LEDdelaytime2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IR translator
|
||||
void IRtranslate()
|
||||
{
|
||||
switch(IRresults.value) {
|
||||
case 0xFFA25D: Serial.println("P"); break; // power
|
||||
case 0xFFE21D: Serial.println("M"); break; // mute
|
||||
case 0xFF629D: Serial.println("m"); break; // mode
|
||||
case 0xFF22DD: Serial.println("p"); break; // pause/play
|
||||
case 0xFF02FD: Serial.println("b"); break; // back
|
||||
case 0xFFC23D: Serial.println("f"); break; // forward
|
||||
case 0xFFE01F: Serial.println("e"); break; // eq
|
||||
case 0xFFA857: Serial.println("-"); break; // vol down
|
||||
case 0xFF906F: Serial.println("+"); break; // vol up
|
||||
case 0xFF9867: Serial.println("r"); break; // return
|
||||
case 0xFFB04F: Serial.println("u"); break; // usb scan
|
||||
case 0xFF6897: Serial.println("0"); break; // number 0
|
||||
case 0xFF30CF: Serial.println("1"); break; // number 1
|
||||
case 0xFF18E7: Serial.println("2"); break; // number 2
|
||||
case 0xFF7A85: Serial.println("3"); break; // number 3
|
||||
case 0xFF10EF: Serial.println("4"); break; // number 4
|
||||
case 0xFF38C7: Serial.println("5"); break; // number 5
|
||||
case 0xFF5AA5: Serial.println("6"); break; // number 6
|
||||
case 0xFF42BD: Serial.println("7"); break; // number 7
|
||||
case 0xFF4AB5: Serial.println("8"); break; // number 8
|
||||
case 0xFF52AD: Serial.println("9"); break; // number 9
|
||||
case 0xFFFFFFFF: Serial.println("R");break; // repeat
|
||||
|
||||
default:
|
||||
Serial.println("Z"); // other button
|
||||
}
|
||||
|
||||
// Do not get immediate repeat keypress
|
||||
delay(500);
|
||||
}
|
||||
|
||||
// serial/IR receive
|
||||
void SERrecv()
|
||||
{
|
||||
static boolean recvInProgress = false;
|
||||
static byte ndx = 0;
|
||||
char startMarker = '#';
|
||||
char endMarker = '@';
|
||||
char rc;
|
||||
|
||||
while (Serial.available() > 0 && SERnewData == false) {
|
||||
// process serial signal
|
||||
rc = Serial.read();
|
||||
|
||||
if(recvInProgress == true) {
|
||||
if(rc != endMarker) {
|
||||
SERrecvChars[ndx] = rc;
|
||||
ndx++;
|
||||
if (ndx >= SERnumChars) {
|
||||
ndx = SERnumChars - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
SERrecvChars[ndx] = '\0'; // terminate the string
|
||||
recvInProgress = false;
|
||||
ndx = 0;
|
||||
SERnewData = true;
|
||||
}
|
||||
}
|
||||
|
||||
else if(rc == startMarker) {
|
||||
recvInProgress = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// display stats on LCD and load average on LED
|
||||
void showNewData()
|
||||
{
|
||||
if(SERnewData == true) {
|
||||
if(DEBUG) {
|
||||
Serial.print("This just in ... ");
|
||||
Serial.println(receivedChars);
|
||||
Serial.println(SERrecvChars);
|
||||
}
|
||||
|
||||
// Print on line 1 or 2
|
||||
// dev: fucking c and its fixed arrays
|
||||
// we have to define 1st character (line number) as BS and when printing, search for that BS character to skip printing that 1 character, grrr
|
||||
if(receivedChars[0] == '1') {
|
||||
if(SERrecvChars[0] == '1') {
|
||||
LcdL1(true);
|
||||
receivedChars[0] = '\b';
|
||||
LcdWrite(receivedChars);
|
||||
SERrecvChars[0] = '\b';
|
||||
LcdWrite(SERrecvChars);
|
||||
}
|
||||
else if(receivedChars[0] == '2') {
|
||||
else if(SERrecvChars[0] == '2') {
|
||||
LcdL2(true);
|
||||
receivedChars[0] = '\b';
|
||||
LcdWrite(receivedChars);
|
||||
SERrecvChars[0] = '\b';
|
||||
LcdWrite(SERrecvChars);
|
||||
}
|
||||
else if(SERrecvChars[0] == '3') {
|
||||
SERrecvChars[0] = ' ';
|
||||
LedShowLoad(SERrecvChars);
|
||||
}
|
||||
|
||||
newData = false;
|
||||
SERnewData = false;
|
||||
}
|
||||
}
|
||||
|
||||
void setup (void) {
|
||||
// Init LCD panel
|
||||
void setup (void)
|
||||
{
|
||||
// init HW
|
||||
LcdSetup();
|
||||
LEDSetup();
|
||||
IRSetup();
|
||||
|
||||
// Init Debugging output
|
||||
if(DEBUG) {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for native USB port only
|
||||
}
|
||||
}
|
||||
|
||||
// Init normal operation
|
||||
else {
|
||||
Serial.begin(9600);
|
||||
}
|
||||
// open serial port
|
||||
Serial.begin(9600);
|
||||
|
||||
// display intros
|
||||
LcdIntro();
|
||||
LedIntro();
|
||||
}
|
||||
|
||||
// main()
|
||||
void loop (void) {
|
||||
// process input
|
||||
recvWithStartEndMarkers();
|
||||
void loop (void)
|
||||
{
|
||||
//process IR signal
|
||||
if(Irrecv.decode(&IRresults)) {
|
||||
IRtranslate();
|
||||
Irrecv.resume(); // receive the next value
|
||||
}
|
||||
|
||||
// process serial input
|
||||
SERrecv();
|
||||
|
||||
// display new data
|
||||
showNewData();
|
||||
}
|
||||
Reference in New Issue
Block a user