Hello I'm writing a program which would send information about cpu usage and free ram memory to arduino and arduino would display it on screen. Program is written with python and to send info I'm using json to encode whole info and send it to arduino, but I don't know how to decode that info on arduino to display it on lcd.... Maybe someone can help?
By far my arduino code was like this:
import psutil, time, sys, serial
import math
import json
z = 0
y = 0
x = 0
port = raw_input("COM port : ")
ser = serial.Serial(port, 9600)
while True:
try:
time.sleep(1)
z = psutil.cpu_percent()
x = psutil.virtual_memory()
y = x.free
y = y/math.pow(1024,2)
data = { 'cpu':z,
'ram':y}
ser.write(str(data))
print 'RAM free', (int(y)), 'mb'
print 'CPU usage', (int(z)), '%'
print json.dumps(data)
except KeyboardInterrupt:
print 'Done'
ser.close()
sys.exit(0)
I get an error which says :
error: initializer fails to determine size of 'json'
I don't know the better way to send this data because I want to decode it and show it on LCD like this:
CPU usage: **%
RAM free: **%
if i would send just z & y to arduino without encode I believe it could not do it because it would be printent as one content? If you know easier way please tell me :((
What does this look like when it gets to the serial port?
Store the data in a NULL terminated array of chars, and use strtok() to parse the data. Of course, it will help to know what the data looks like on the Arduino side.
manic9:
So what would you recommend to use? Or how to do this?
Develop your parsing code using the serial monitor. You may need to figure out an easier way to package the data from the pc before sending it. Do you have an example of the actual data string sent fom the pc?
Ok last question, the readCSV() function that Robin2 showed me in his code takes a string(text), an integer and a float and seperates them, in my case I need that it only take two numbers sent as strings seperated by kommas, I tried to modificate code, but now it prints ram perfectly and do not print CPU, what is wrong?
Here's the arduino code:
#include <LiquidCrystal.h>
LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);
const byte buffSize = 32;
char inputSeveral[buffSize]; // space for 31 chars and a terminator
byte maxChars = 12; // a shorter limit to make it easier to see what happens
// if too many chars are entered
int cpu = 0;
int ram = 0;
char inputCsvString[12];
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
}
void loop() {
readCSV();
}
void readCSV() {
// this function expects a series of comma separated values
// for this demo the sequence of items must be a string, an integer, a float
// for example testing, 123 , 4567.89
// spaces around the commas are optional
// first read severalChars into the array inputSeveral
inputSeveral[0] = 0;
maxChars = buffSize - 1; // use full size of buffer for this function
byte charCount = 0;
byte ndx = 0;
if (Serial.available() > 0) {
while (Serial.available() > 0) {
if (ndx > maxChars - 1) {
ndx = maxChars;
}
inputSeveral[ndx] = Serial.read();
ndx ++;
charCount ++;
}
if (ndx > maxChars) {
ndx = maxChars;
}
inputSeveral[ndx] = 0;
// now we need to split the received string into its parts
// this is done by strtok() which looks for the token - the comma in this case
char * partOfString; // this is used by strtok() as an index
partOfString = strtok(inputSeveral,",");
cpu = atoi(partOfString); // convert this part to an integer
partOfString = strtok(NULL, ",");
ram = atoi(partOfString); // convert this part to a float
lcd.clear();
lcd.setCursor(0,0);
lcd.print("CPU: ");
lcd.print(cpu);
lcd.print(" %");
lcd.setCursor(0,1);
lcd.print("RAM: ");
lcd.print(ram);
lcd.print(" mb");
delay(1000);
}
else {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("DUOMENU NERA");
}
}
Python code here:
import psutil, time, sys, serial
import math
z = 0
y = 0
x = 0
port = raw_input("COM port : ")
ser = serial.Serial(port, 9600)
while True:
try:
time.sleep(1)
z = psutil.cpu_percent()
x = psutil.virtual_memory()
y = x.free
y = y/math.pow(1024,2)
data = (z, y)
ser.write(str(data))
print 'RAM free', (int(y)), 'mb'
print 'CPU usage', (int(z)), '%'
except KeyboardInterrupt:
print 'Done'
ser.close()
sys.exit(0)
Can you print the contents of inputSeveral immediately before you start trying to parse it?
Have you tried sending data to your revised program using the Serial Monitor.
It might be a good idea to change
if (Serial.available() > 0) {
to reflect the number of characters you are expecting - if the length will always be the same.
In this demo the process of receiving data is a little different - the data is surrounded by start- and end-markers so the Arduino knows it has received everything. That means it can receive a variable number of characters with certainty.
It's difficult to know what to include in each demo to avoid confusing people with too much info.
If I do it like this in python program
data = ("test", z, y) // where z = cpu and y= ram
Ser.write(str(data))
Then I can do everything like in your demo because I send text and two numbers, but if I remove "test" it doesn't work with changes that I made and prints only Ram, and leaving cpu = 0; I will try to change what you just said, but I don't know what will be the exact lengh of message because it changes every second...
Maybe you could detect all three parts in your Arduino sketch and just ignore the first item?
More significantly, you failed to answer the main question I asked - printing the contents of inputSeveral. I don't understand how you expect to solve the problem without looking at the data that is causing it. The Arduino may not be receiving what was sent by Python.
Arduino is receiving full message that is send over python program I have tried to print it as one content it worked. Yeah I have already done that arduino is ignoring the first one and printing second and third item and it works perfectly, just I wanted to make program a little shorter cutting off unnecesary pieces.
Below is a simple data parsing setup you might consider.
//zoomkat 11-12-13 String capture and parsing
//from serial port input (via serial monitor)
//and print result out serial port
//copy test strings and use ctrl/v to paste in
//serial monitor if desired
// * is used as the data string delimiter
// , is used to delimit individual data
String readString; //main captured String
String angle; //data String
String fuel;
String speed1;
String altidude;
int ind1; // , locations
int ind2;
int ind3;
int ind4;
void setup() {
Serial.begin(9600);
Serial.println("serial delimit test 11-12-13"); // so I can keep track of what is loaded
}
void loop() {
//expect a string like 90,low,15.6,125*
//or 130,hi,7.2,389*
if (Serial.available()) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == '*') {
//do stuff
Serial.println();
Serial.print("captured String is : ");
Serial.println(readString); //prints string to serial port out
ind1 = readString.indexOf(','); //finds location of first ,
angle = readString.substring(0, ind1); //captures first data String
ind2 = readString.indexOf(',', ind1+1 ); //finds location of second ,
fuel = readString.substring(ind1+1, ind2+1); //captures second data String
ind3 = readString.indexOf(',', ind2+1 );
speed1 = readString.substring(ind2+1, ind3+1);
ind4 = readString.indexOf(',', ind3+1 );
altidude = readString.substring(ind3+1); //captures remain part of data after last ,
Serial.print("angle = ");
Serial.println(angle);
Serial.print("fuel = ");
Serial.println(fuel);
Serial.print("speed = ");
Serial.println(speed1);
Serial.print("altidude = ");
Serial.println(altidude);
Serial.println();
Serial.println();
readString=""; //clears variable for new input
angle="";
fuel="";
speed1="";
altidude="";
}
else {
readString += c; //makes the string readString
}
}
}