hi all
i am tryint to print the information that is read through the softwareserial pins (A4,A5) and output it to both the serial console, and the TFT display.
i can get it out to the console, but just get 3 jibberish charactors on the TFT. i am not to sure where my issue lies, as to my reading of the code it seems correct. but clearly not.
/*
Reads information from MPPT controllers and displays it on the LCD, also outputs the information via SERIAL @ 9600 BAUD
* **********PINOUTS********
Controller:
________________________
| 4 3 2 1 |
| . . . . |
| VCC TX RX GND |
| (RED) (YEL)(WHI)(BLK) |
| _______ |
|_______| |________|
Odroid SHOW:
5V - To VCC (RED) Pin (4)
A4 - To TX (YEL) Pin (3)
A5 - To RX (WHI) Pin (2)
GND - To GND (BLK) Pin (1)
*/
const char version[] = {"1.0 27/04/2017"};
#include <SoftwareSerial.h>
#include <SPI.h>
#include <Wire.h>
#include "TimerOne.h"
#include <Adafruit_GFX.h>
#include <ODROID_Si1132.h>
#include <ODROID_Si70xx.h>
#include <Adafruit_ILI9340.h>
#define _sclk 13
#define _miso 12
#define _mosi 11
#define _cs 10
#define _dc 9
#define _rst 8
// Settings below are to control the Backlight brightness and rotation of the Odroid-SHOW LCD Display
uint8_t ledPin = 5;
uint8_t pwm = 255;
uint8_t textSize = 2;
uint8_t rotation = 1;
uint16_t foregroundColor, backgroundColor;
Adafruit_ILI9340 tft = Adafruit_ILI9340(_cs, _dc, _rst);
ODROID_Si70xx si7020;
ODROID_Si1132 si1132;
void initPins()//This is the Backlight PWM control pin settings
{
pinMode(ledPin, OUTPUT);
analogWrite(ledPin, pwm);
}
SoftwareSerial MPPTSERIAL(A4, A5); // RX, TX
void setup() {
// initialize the sensors
tft.begin();
si1132.begin();
// initialize the digital pins
initPins();
delay(500);
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Jasons MPPT Intrface Module");
Serial.print("Module Firmware Version ");
Serial.println(version);
tft.setRotation(rotation);
tft.setTextSize(textSize);
tft.setCursor(25, 25);
tft.print("Jasons");
tft.setCursor(25, 45);
tft.print("MPPT Intrface Module");
tft.setCursor(25, 85);
tft.print("Module Firmware Version");
tft.setCursor(25, 105);
tft.print(version);
delay(2500);
// set the data rate for the SoftwareSerial port
MPPTSERIAL.begin(19200);
Serial.println("MPPT Serial Connection Initialised");
tft.setRotation(rotation);
tft.setTextSize(textSize);
tft.setCursor(25, 145);
tft.print("MPPT Serial");
tft.setCursor(25, 165);
tft.print("Connection Initialised");
delay(2500);
tft.fillScreen(backgroundColor);
}
void loop() {
Printinfo();
}
void Printinfo()
{
if (MPPTSERIAL.available()) {
Serial.write(MPPTSERIAL.read());
tft.setRotation(rotation);
tft.setTextSize(textSize);
tft.setCursor(20, 20);
tft.print(MPPTSERIAL.read());
}
if (Serial.available()) {
MPPTSERIAL.write(Serial.read());
}
}
any pointers?
thanks,
Jason
Forget all the serial stuff for now. Do you see the messages sent in setup() on the TFT ?
UKHeliBob:
Forget all the serial stuff for now. Do you see the messages sent in setup() on the TFT ?
yes, that is all working as it should. then it clears, well fills with
tft.fillScreen(backgroundColor);
thats all sweet. just the serial part has me a bit lost.
Jason
if (MPPTSERIAL.available())
{
Serial.write(MPPTSERIAL.read());
tft.setRotation(rotation);
tft.setTextSize(textSize);
tft.setCursor(20, 20);
tft.print(MPPTSERIAL.read());
}
You are checking whether a byte is available then reading twice. Instead, if data is available, read it into a variable then print the variable as many times as you want.
i have had it running for a period of time and it seems that the jarbled text is "filling in"
this is a copy/[aste from the serial console, this is what im hoping to get on the tft.
PID 0xA042
FW 123
SER# HQ155154LPY
V 0
I 0
VPV 0
PPV 0
CS 0
ERR 0
LOAD OFF
IL 0
H19 4438
H20 0
H21 0
H22 38
H23 136
HSDS 74
Checksum
possibly caused by too much info trying to hit the tft?
thats just the info thats sent out by the controller. i cant change it, but even if it scrolls it and i loo=se some, thats fine. just want to see it for proof of concept so to speak.
Jason
Did you note what I said in post #3 and make the changes ?
UKHeliBob:
if (MPPTSERIAL.available())
{
Serial.write(MPPTSERIAL.read());
tft.setRotation(rotation);
tft.setTextSize(textSize);
tft.setCursor(20, 20);
tft.print(MPPTSERIAL.read());
}
You are checking whether a byte is available then reading twice. Instead, if data is available, read it into a variable then print the variable as many times as you want.
sorry, that is beyone my level of experience. haha. cany you point me to where i can read about what i need to do? i came across Serial.read() - Arduino Reference . that mentions something about incommingbyte and looks like its storing it to an 'int'. however, would that work for my application? as i am sending alot of information?
Jason
Your current code with my comments added
if (MPPTSERIAL.available()) //one or more bytes is available to read
{
Serial.write(MPPTSERIAL.read()); //read a byte from MPPTSERIAL and write it to Serial.
tft.setRotation(rotation);
tft.setTextSize(textSize);
tft.setCursor(20, 20);
tft.print(MPPTSERIAL.read()); //read a second (different) byte from MPPTSERIAL whether or not one is available and write it to Serial.
}
Try this
if (MPPTSERIAL.available())
{
char inComing = MPPTSERIAL.read(); //read the available byte into a variable
Serial.write(inComing); //output the byte to Serial
tft.setRotation(rotation);
tft.setTextSize(textSize);
tft.setCursor(20, 20); //you probably want to move the cursor each time you print a byte
tft.print(inComing); //output the same byte to TFT
}
ok,
well that gives me an output on the serial console, and just a white box on the tft.
but its a step forward atleast.
the mppt controller updates, and sends out new data every 1 second.
i noticed that you wrote it to a 'char' variable as that is only 1 byte of data, will that be enough to hold all that was in my earlier post? im not sure how to calculate the size that is needed to hold it?
could the reason for the white box be due to not enough space to hold the data in the 'char' variable?
just to check, at the top i have declared it like this
char inComing ;
do i have that correct?
just to check, at the top i have declared it like this
You don't need to do that. What you are doing is to declare a global (available anywhere in the program) variable but my change to your program declared a local variable with the same name which is used to hold the incoming byte. It will work with both declared but I suggest that you do one or the other.
As to handling multiple incoming characters, you can either build up a string of chars and print all of when it is complete or print each character as it is received.
Note that in reply #7 I noted that you might want to move the TFT cursor after printing each character. Whether you print one character at a time or save to a string for printing later you will need to put the cursor in the right place before printing a new message.
A couple of questions:
How will you know that the string is complete ?
How long will the string be ?
How much space is available to print on the TFT ?
so declaring it as a char variable, it cant auto size it to whats required for the amount of data comming in?
No
should the library not take care of moving the cursor to print the text, i have told it where i want it to start printing, but from there....?
Your present code puts the cursor back at 20, 20 for each character so the output stays in the same place.
this i dont know, this is the first time i have played with actually getting the serial to do something other than just display for me to read
You will need to know that the input is complete in order to clear the screen, scroll the screen or position the cursor for subsequent messages
i assume you mean physical, it is a 2.2" TFT.
I actually meant the number of pixels available to print the incoming data. What should happen when the screen is full ?
Hi all, sorry for my late respone
the TFT is a 240 x 320 resolution. I am unsure what happens when the screen is full, i am using an odroid-SHOW unit.
possibly another way of going about what i am after, is how can i search for text or a string of text in the serial data, as i can then save that as a variable and then print that, as i dont need all the data that is sent over the serial.
This is the data thats sent over the serial,
PID 0xA042
FW 123
SER# HQ155154LPY
V 0
I 0
VPV 0
PPV 0
CS 0
ERR 0
LOAD OFF
IL 0
H19 4438
H20 0
H21 0
H22 38
H23 136
HSDS 74
Checksum
i only need the following values "V, I,VPV,PPV,LOAD,H19,IL" i have tried searching how to look for the 'header'(not sure what its called, but lets take "V" and then save the value from that as a variable. but perhaps im just not searching for the correct information, as i cant find how do discern that information and have it saved as a variable.
in the beginngin part of the code, as it initialises, i have it printong some information to the TFT, and i have set its starting location. it just wrote the text as i expected it to. so if it set the start location for the tft print of the serial information, i would have thought that it should just shift the cursor accordingly.
i will leave the serial read declarations at the top as a global, as i have thought of something else i would like the odroid to do and it will be handy having the info stored there to call upon for the extra functions.
Jason
ok, so after much research, i am still lost as to what i need to look for.
i have tried everything i can think of and the closest i have gottent is serial.parase
is this along the right track? i have found a bir relating to storing information from a serial string if it comes in as a CSV or has a delimiter like a "," but the serial gives me a "header" and i want it to look for the header and then store the value that comes from it.
here is a copy of the section from the whitepaper of the mppt controller
Message format
The device transmits blocks of data at 1 second intervals. Each field is sent using the following format:
The identifiers are defined as follows:
Identifier Meaning
A carriage return followed by a line feed (0x0D, 0x0A).
An arbitrary length label that identifies the field. Where applicable, this will be the same as the label that is used on the LCD.
A horizontal tab (0x09).
The ASCII formatted value of this field. The number of characters transmitted depends on the magnitude and sign of the value.
Data integrity
The statistics are grouped in blocks with a checksum appended. The last field in a block will always be “Checksum”. The value is a single byte, and will not necessarily be a printable ASCII character. The modulo 256 sum of all bytes in a block will equal 0 if there were no transmission errors. Multiple blocks are sent containing different fields.
any further ideas?
Jason
i only need the following values "V, I,VPV,PPV,LOAD,H19,IL"
Is the data always in the same format and in the same order ? If so then you could start by ignoring lines that you are not interested in. Read and discard 3 lines and you know that the next thing will be a line starting with V containing a number that you are interested in. Read the V and space and the next thing is the number.
Yes. That's what I am trying to do. But don't understand how to look for "V" capture its value then ignore and catch the next label I'm after.
Jason
hi all
ok, so after looking around, reading and trying other bits and peices of code. (aswell as getting help from another forum) i have arrived with this code
/*
Odroid-SHOW MPPT Intrface Module
Reads information from MPPT controllers and displays it on the LCD, also outputs the information via SERIAL @ 9600 BAUD
* **********PINOUTS********
MPPT Controller:
________________________
| 4 3 2 1 |
| . . . . |
| VCC TX RX GND |
| (RED) (YEL)(WHI)(BLK) |
| _______ |
|_______| |________|
Odroid SHOW:
5V - To VCC (RED) Pin (4)
A4 - To TX (YEL) Pin (3)
A5 - To RX (WHI) Pin (2)
GND - To GND (BLK) Pin (1)
*/
const char version[] = {"1.0 27/04/2017"};
//Below is the required Library inclusions
#include <SoftwareSerial.h>
#include <SPI.h>
#include <Wire.h>
#include "TimerOne.h"
#include <Adafruit_GFX.h>
#include <ODROID_Si1132.h>
#include <ODROID_Si70xx.h>
#include <Adafruit_ILI9340.h>
//Below is the required Pin Defines and links for the TFT
#define _sclk 13
#define _miso 12
#define _mosi 11
#define _cs 10
#define _dc 9
#define _rst 8
Adafruit_ILI9340 tft = Adafruit_ILI9340(_cs, _dc, _rst);
ODROID_Si70xx si7020;
ODROID_Si1132 si1132;
// Settings below are to control the Backlight brightness and rotation of the Odroid-SHOW LCD Display
uint8_t ledPin = 5;
uint8_t pwm = 255;
uint8_t textSize = 2;
uint8_t rotation = 1; //0 = Portrait, 1 = Landscape
//Below sets up the SoftwareSerial ports so that the arduino can receive information from the MPPT Controller aswell as pass its information through to the hardware UART
SoftwareSerial MPPTSERIAL(A4, A5); // RX, TX
void setup() {
// initialize the TFT and the digital pins for TFT backlight control
tft.begin();
si1132.begin();
initPins();
delay(50);
// Open serial communications on hardware UART and wait for port to open:
Serial.begin(9600);
delay(50);
//Below Prints the module Version information to both the Serial monitor and the TFT
Serial.println("Odroid-SHOW MPPT Intrface Module");
Serial.print("Module Firmware Version ");
Serial.println(version);
tft.fillScreen(ILI9340_BLACK);
tft.setRotation(rotation);
tft.setTextSize(textSize);
tft.setCursor(25, 25);
tft.print("Odroid-SHOW");
tft.setCursor(25, 45);
tft.print("MPPT Intrface Module");
tft.setCursor(25, 85);
tft.print("Module Firmware Version");
tft.setCursor(25, 105);
tft.print(version);
delay(2500);
// set the data rate for the SoftwareSerial port and print to TFT when initialized
MPPTSERIAL.begin(19200);
Serial.println("MPPT Serial Connection Initialized");
tft.setRotation(rotation);
tft.setTextSize(textSize);
tft.setCursor(25, 145);
tft.print("MPPT Serial");
tft.setCursor(25, 165);
tft.print("Connection Initialized");
delay(2500);
tft.fillScreen(ILI9340_BLACK);
}
void loop() {
if (MPPTSERIAL.available())
{
char inComing = MPPTSERIAL.read(); //read the available byte into a variable
[B]String BattVoltage = getValue(inComing, "/n", 3).toString();[/B]
[B]String PVCurrent = getValue(inComing, "/n", 4).toString();[/B]
[B]String PVVoltage = getValue(inComing, "/n", 5).toString();[/B]
Serial.println(BattVoltage); //output the Battery Voltage to Serial Monitor
Serial.println(PVCurrent); //output the PV Charge Current to Serial Monitor
Serial.println(BattVoltage); //output the PV Voltage to Serial Monitor
tft.setRotation(rotation);
tft.setTextSize(textSize);
tft.setCursor(25, 25);
tft.print("Battery Voltage:")(BattVoltage); //output Battery Voltage to TFT
tft.setCursor(25, 145);
tft.print ("PV Current:")(PVCurrent); //output PV Charge Current to TFT
tft.setCursor(25, 165);
tft.print("PV Voltage:")(PVVoltage); //output PV Voltage to TFT
tft.fillScreen(ILI9340_BLACK);
}
if (Serial.available()) {
MPPTSERIAL.write(Serial.read());
}
}
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = { 0, -1 };
int maxIndex = data.length() - 1;
for (int i = 0; i <= maxIndex && found <= index; i++) {
if (data.charAt(i) == separator || i == maxIndex) {
found++;
strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}
//Below is the various Function Calls
//This is the Backlight PWM control pin settings
void initPins(){
pinMode(ledPin, OUTPUT);
analogWrite(ledPin, pwm);
}
and that is giving me this error and the IDE highlights the above lines (shown in bold) as the source of the error
converting to 'String' from initializer list would use explicit constructor 'String::String(char)'
from what i can gather, i may need to change it from a srting to an INT or a CHAR, but all the examples i have tried and just guessed out of hope have failed.
any pointers?
Jason