Hello !
I'm a new french Arduino adept therefore please forget my mistakes
I'm working for a system which will be control by Serial commands. I must retrieve the command that I entered on the console.
Example :
I write "on" and Arduino light the led.
But it is a real headache...
That's what I've done and that doesn't work:
int character_available = 0;
char character;
int i = 0;
void setup()
{
Serial.begin(9600);
}
void loop()
{
}
void serialEvent() //declaration of interrupt function on the serial port
{
character_available = Serial.available(); // variable containing the number of characters available in the buffer
char messageString[character_available]; //array will contain this message
i = 0;
while(character_available > 0) // so long there are characters to read
{
character = Serial.read();
messageString[i] = character;
character_available = Serial.available();
i++;
message = message, messageString[i]; //this must register the string and if we do Serial.print(message); it show "Hello" for example
}
}
It's getting later in France. Maybe I made ??a mistake beast... But thanks you and see you soon
I don't really know how string works, it's true. But this mistakes comes from my copy / paste.
I add
char* message;
but I don't know how I can correct
message = message, messageString*;* it is message = message + messageString*;* or message = message . messageString*;* ?
very simple code to turn the arduino LED on and off. Type on or off in the serial monitor then send.
// zoomkat 8-6-10 serial I/O string test
// type a string in serial monitor. then send or enter
// for IDE 0019 and later
int ledPin = 13;
String readString;
void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
Serial.println("serial on/off test 0021"); // so I can keep track
}
void loop() {
while (Serial.available()) {
delay(10);
char c = Serial.read();
readString += c;
}
if (readString.length() >0) {
Serial.println(readString);
if(readString.indexOf("on") >=0)
{
digitalWrite(ledPin, HIGH);
}
if(readString.indexOf("off") >=0)
{
digitalWrite(ledPin, LOW);
}
readString="";
}
}
character_available = Serial.available(); // variable containing the number of characters available in the buffer
char messageString[character_available]; //array will contain this message
That part is flawed. You are making a dynamic array to hold the "available" number of characters, however more may arrive while you are reading them. That is the subsequent loop may well overflow the array. Plus you haven't allowed room for a terminator.
I took the code this morning, here is what I did :
void serialEvent()
{
while (Serial.available()) {
delay(10);
char c = Serial.read();
readString += c;
}
Serial.println("");
Serial.println("-----");
if (isDigit(readString))
{
numberWanted = (readString - '0');
Serial.print("Pushes number of the day ");
Serial.print(numberWanted);
Serial.print(" is : ");
Serial.println(round(counterByDay[numberWanted]));
}
else
{
Serial.println("This is not a number.");
}
Serial.println("-----");
Serial.println("");
readString = 0;
}
But now, I realize that I have errors in the rest of the program, and I doubt that it comes from this last piece.
Every day I record the number of pulses and I stock it all in a table, here is my method of storage:
//actualise time
time = millis();
//preparing time to verify that is a multiple of one day, a day = 15000 ms (to test
time = time/(round(time / 15000));
//if time = one day, save the number
if ((time >= 15000) && (time <= 15100) && (numberSaving == 0) && (millis() > 3000))
{
//operations to save the number with the date in an array:
day++;
counterByDay[day] = buttonPushCounter;
//initialise counter
buttonPushCounter = 0;
numberSaving = 1;
}
//If the number have been saved, and if won't be save a second time, we initialise numberSaving
else if (((time < 15000) || (time > 15100)) && (numberSaving == 1))
{
numberSaving = 0;
}
If I don't have problem on that 2 parts, I'll show you how I write on the screen.
//Prepare control by console
int numberWanted;
char readString;
boolean stringComplete = false;
int charAvailable;
void setup()
{
Serial.begin(9600);
}
void loop()
{
[......]
if (stringComplete)
{
//if readString is a number, show the counter of this day
if (isDigit(readString))
{
numberWanted = (readString - '0');
Serial.print("Le nombre de basculement du jour ");
Serial.print(numberWanted);
Serial.print(" est : ");
Serial.println(round(counterByDay[numberWanted]));
}
else //command unknow
{
Serial.println("Ceci n'est as un nombre.");
}
//inizialise string;
readString = 0;
stringComplete = false;
}
}
//Now, what prog must do if commands are sent
void serialEvent()
{
//creation of the string
while (Serial.available())
{
delay(10);
char c = Serial.read();
readString += c;
charAvailable = Serial.available();
if (charAvailable == 0)
{
stringComplete = true;
}
}
}
I show the trick "numberWanted = (readString - '0');" to convert readString in a number. That's not possible ?
// this constant won't change:
const int buttonPin = 2; // the pin that the pushbutton is attached to
const int ledPin = 13; // the pin that the LED is attached to
const int buttonPin2 = 3; // second button to know the numbers of everydays
const int ledPin2 = 8;
// Variables will change:
int buttonPushCounter = 0; // counter for the number of button presses
int buttonState = 0; // current state of the button
int buttonState2 = 0;
int lastButtonState = 0; // previous state of the button
int lastButtonState2 = 0;
double time = 0; // will contain the hour
int numberSaving = 0; //permite to know if the number have been already saved
int i; //to explore the array
//Array which will contain de number of the push by day
int day = 0; //not one because the programm will automatically increment
float counterByDay[] = {}; //this array will begin on 1, not on 0
//Prepare control by console
int numberWanted;
char readString;
boolean stringComplete = false;
int charAvailable;
void setup()
{
// initialize the button pin as a input:
pinMode(buttonPin, INPUT);
pinMode(buttonPin2, INPUT);
// initialize the LED as an output:
pinMode(ledPin, OUTPUT);
pinMode(ledPin2, OUTPUT);
// initialize serial communication:
Serial.begin(9600);
// little home message
Serial.println("------COMPTEUR D'IMPULSIONS-------");
Serial.println("Nb: appuyer sur le bouton pour obternir les resultats des derniers jours.");
Serial.println("");
}
void loop() {
// read the pushbutton input pin:
buttonState = digitalRead(buttonPin);
// turns on the LED when button pushed
digitalWrite(ledPin, buttonState);
// compare the buttonState to its previous state
if ((buttonState != lastButtonState) && (millis() > 3000)) //"millis() > 3000" permite to avoid the inconvenience of starting
{
// if the state has changed, increment the counter
if (buttonState == HIGH)
{
// if the current state is HIGH then the button
// wend from off to on:
buttonPushCounter++;
Serial.print("Compteur: ");
Serial.println(buttonPushCounter);
Serial.println("");
}
else {
// if the current state is LOW then the button
// wend from on to off:
Serial.println("+1");
}
}
// save the current state as the last state,
//for next time through the loop
lastButtonState = buttonState;
//actualise time
time = millis();
//preparing time to verify that is a multiple of one day
time = time/(round(time / 15000));
//if time = one day, save the number
if ((time >= 15000) && (time <= 15100) && (numberSaving == 0) && (millis() > 3000)) //REAL: if(time >= 86400000 && time <= 86402000)
{
//operations to save the number with the date in an array:
day++;
counterByDay[day] = buttonPushCounter;
//initialise counter
buttonPushCounter = 0;
//write it on the sreen
Serial.println("");
Serial.println("-----");
Serial.print("Jour ");
Serial.print(day);
Serial.print(", nombre de basculement: ");
Serial.println(round(counterByDay[day]));
Serial.println("-----");
Serial.println("");
numberSaving = 1;
}
//If the number have been saved, and if won't be save a second time, we initialise numberSaving
else if (((time < 15000) || (time > 15100)) && (numberSaving == 1))
{
numberSaving = 0;
}
//This part must show all the array when button 2 is pressed
// read the pushbutton2 input pin:
buttonState2 = digitalRead(buttonPin2);
// turns on the LED 2 when button pushed
digitalWrite(ledPin2, buttonState2);
// compare the buttonState2 to its previous state
if ((buttonState2 != lastButtonState2) && (millis() > 3000))
{
// if the state has changed,
if (buttonState2 == HIGH)
{
// if the current state is HIGH then the button
// wend from off to on
//Here the programm personnalise the announcement for 3 category : the first day, the second, more than 2
Serial.println("");
Serial.println("-----");
if (day == 0)
{
Serial.print("Compteur du premier jour (jour actuel): ");
Serial.print(buttonPushCounter);
Serial.println("");
}
else if (day == 1)
{
Serial.println("Compteur d'hier et d'aujourd'hui : ");
Serial.print("- Hier : ");
Serial.println(round(counterByDay[1]));
Serial.print("- Depuis ce matin : ");
Serial.println(buttonPushCounter);
}
else //this explains that there are a lot of day
{
Serial.print("Compteur ");
Serial.print(day);
Serial.println(" derniers jours: ");
//listing all days with an array
for (i = 1; i < (day+1); i = i + 1)
{
Serial.print("- Jour ");
Serial.print(i);
Serial.print(" : ");
Serial.println(round(counterByDay[i])); //round could be delete
}
Serial.print("- Depuis ce matin : ");
Serial.println(buttonPushCounter);
}
Serial.println("-----");
Serial.println("");
}
}
// save the current state as the last state,
//for next time through the loop
lastButtonState2 = buttonState2;
if (stringComplete)
{
//if readString is a number, show the counter of this day
Serial.println("");
Serial.println("-----");
if (isDigit(readString))
{
numberWanted = (readString - '0');
Serial.print("Le nombre de basculement du jour ");
Serial.print(numberWanted);
Serial.print(" est : ");
Serial.println(round(counterByDay[numberWanted]));
}
else //command unknow
{
Serial.println("Ceci n'est as un nombre.");
}
Serial.println("-----");
Serial.println("");
//inizialise string;
readString = 0;
stringComplete = false;
}
}
//Now, what prog must do if commands are sent
void serialEvent()
{
//creation of the string
while (Serial.available())
{
delay(10);
char c = Serial.read();
readString += c;
charAvailable = Serial.available();
if (charAvailable == 0)
{
stringComplete = true;
}
}
}
I'm a new user and I must learn quickly because I'm working on a project baccalaureate, sorry if I made strange mistakes :~
Copy SerialReceiver.h and SerialReceiver.cpp in your sketch folder.
Change processMessage() function to suit your needs.
Make sure you call run() in loop().
SerialReceiver.h
#ifndef _SERIAL_RECEIVER_H
#define _SERIAL_RECEIVER_H
#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
// ASCII codes - see http://www.asciitable.com/
#define CR 0x0D
#define LF 0x0A
// type of receive error
typedef enum {
ERR_NONE, // there was no error
ERR_TIMEOUT, // the next byte took too long to arrive
ERR_BUFFERFULL // the receive buffer was too small to store all the incoming bytes
} SerialRecvError;
typedef void (*receiveHandler)(const char* buf, SerialRecvError err);
class SerialReceiver {
public:
SerialReceiver(receiveHandler f, unsigned long receiveTimeout);
// receive buffer size (including null terminator)
static const byte RECV_BUF_SIZE = 30;
// is the specified char an end-of-message marker ?
boolean isEndOfMessage(char ch);
// to be called in loop()
void run();
private:
// receive buffer
char _recvBuf[RECV_BUF_SIZE];
// number of bytes currently storedn in the receive buffer
byte _recvBufCnt;
// whan was the last byte received ?
unsigned long _lastRecvTimeMs;
// max delay between two consecutive bytes in the serial stream
unsigned long _receiveTimeout;
// poiter to message processing function
receiveHandler _receiveHandler;
};
#endif
SerialReceiver.cpp
#include "SerialReceiver.h"
SerialReceiver::SerialReceiver(receiveHandler f, unsigned long receiveTimeout) {
_receiveHandler = f;
_receiveTimeout = receiveTimeout;
_recvBufCnt = 0;
}
boolean SerialReceiver::isEndOfMessage(char ch) {
return (ch == CR) || (ch == LF);
}
void SerialReceiver::run() {
if (Serial.available()) {
char ch = Serial.read();
if (isEndOfMessage(ch)) {
if (_recvBufCnt > 0) {
_recvBuf[_recvBufCnt] = 0;
if (_receiveHandler != NULL) {
(*_receiveHandler)(_recvBuf, ERR_NONE);
}
_recvBufCnt = 0;
}
}
else if (_recvBufCnt < (RECV_BUF_SIZE - 1)) { // notice - 1 to leave room for the NULL terminator
_recvBuf[_recvBufCnt] = ch;
_recvBufCnt++;
_lastRecvTimeMs = millis();
}
else {
// buffer full - byte lost
_recvBuf[_recvBufCnt] = 0;
if (_receiveHandler != NULL) {
(*_receiveHandler)(_recvBuf, ERR_BUFFERFULL);
}
_recvBufCnt = 0;
}
}
if (_recvBufCnt > 0) {
if (millis() - _lastRecvTimeMs > _receiveTimeout) {
_recvBuf[_recvBufCnt] = 0;
if (_receiveHandler != NULL) {
(*_receiveHandler)(_recvBuf, ERR_TIMEOUT);
}
_recvBufCnt = 0;
}
}
}
Example sketch
#include "SerialReceiver.h"
// called when a full messages has been received
void processMessage(const char* buf, SerialRecvError err) {
// do something with the received string
Serial.print("Received: ");
Serial.println(buf);
switch(err) {
case ERR_NONE:
break;
case ERR_TIMEOUT:
Serial.println("Timeout detected.");
break;
case ERR_BUFFERFULL:
Serial.println("Buffer full.");
break;
}
}
SerialReceiver rec(processMessage, 10);
void setup() {
Serial.begin(115200);
}
void loop() {
rec.run();
}
Oh god, I didn't see
That's work but it's not what I wan't...
But I think the last code I have posted is good but I have a just a problem with my array or with string. I was testing it on Gobetwino when I see "is not a well formed command string" for all I wrote on my program... Can you help me ?
If you want help with Gobetwino, then you need to enable logging within Gobetwino so that you can see what strings it received from the Arduino and what messages it displayed, and post the actual log output from Gobetwino (in its entirety).
If you want help with Gobetwino, then you need to enable logging within Gobetwino so that you can see what strings it received from the Arduino and what messages it displayed, and post the actual log output from Gobetwino (in its entirety).
The serial data sent to GoBetwino IS displayed, with no need to enable logging it.
I was just saying that my problem is probably either my table or value chains of nature, or display on the console. Finally it is revealed that Gobetwino, I think.