How to store & call multiple letters in arduino? - arrays

Im new to programming, and I'm trying to make a program that adjusts LEDs according to the serial input.
#define Bathroom 13 //LED connected to pin13 named bathroom
#define Livingroom 9 //LED connected to pin9 named livingroom
char *myStrings[] = {"bathdim","bathbright","livingdim","livingbright","beddim","bedbright"};
void setup(){
pinMode(Bathroom, OUTPUT);
pinMode(Livingroom, OUTPUT);
Serial.begin(9600);
}
void loop() {
if(Serial.read() == *myStrings[0]){
Serial.println(*myStrings[0]); // prints "bathdim" on the serial monitor
digitalWrite(Bathroom,0); // turns lights off
delay(100);
}
if(Serial.read() == *myStrings[1]){ // prints "bathbright" on the serial monitor
Serial.println(*myStrings[1]); // turns lights on
digitalWrite(Bathroom,1);
delay(100);
}
if(Serial.read() == *myStrings[2]){
Serial.println(*myStrings[2]);
digitalWrite(Livingroom,0);
delay(100);
}
if(Serial.read() == *myStrings[3]){
Serial.println(*myStrings[3]);
digitalWrite(Livingroom,1);
delay(100);
}
}
When running the code, I typed in "bathbright" which should have turned the lights on, but I didn't work, and the Serial.println(*myStrings[1]) only prints letter "b", not "bathbright"
can anyone help?
EDIT
ok, I removed the * and now the code is as follows:
#define Bathroom 13 //LED connected to pin13 named bathroom
#define Livingroom 9 //LED connected to pin9 named livingroom
char *myStrings[] = {"bathdim","bathbright","livingdim","livingbright","beddim","bedbright"};
void setup(){
pinMode(Bathroom, OUTPUT);
pinMode(Livingroom, OUTPUT);
Serial.begin(9600);
}
void loop() {
if(Serial.read() == *myStrings[0]){
Serial.println(myStrings[0]);
digitalWrite(Bathroom,0);
delay(100);
}
if(Serial.read() == *myStrings[1]){
Serial.println(myStrings[1]);
digitalWrite(Bathroom,1);
delay(100);
}
if(Serial.read() == *myStrings[2]){
Serial.println(myStrings[2]);
digitalWrite(Livingroom,0);
delay(100);
}
if(Serial.read() == *myStrings[3]){
Serial.println(myStrings[3]);
digitalWrite(Livingroom,1);
delay(100);
}
}
The code works well initially but after a few inputs of bathbright and bathdim, he serial print does not print the correct words and the LEDs does not always respond...
FINAL CODE:
#define Bathroom 13 //LED connected to pin13 named bathroom
#define Livingroom 9 //LED connected to pin9 named livingroom
void setup(){
Serial.begin(9600);
pinMode(Bathroom, OUTPUT);
pinMode(Livingroom, OUTPUT);
}
void loop(){
String str = Serial.readString();
if(str.indexOf("bathdim") > -1){
Serial.println("dimming bathroom");
digitalWrite(Bathroom,0);
}
if(str.indexOf("bathbright") > -1){
Serial.println("lighting up bathroom");
digitalWrite(Bathroom,1);
}
if(str.indexOf("livingdim") > -1){
Serial.println("dimming Livingroom");
digitalWrite(Livingroom,0);
}
if(str.indexOf("livingbright") > -1){
Serial.println("lighting up Livingroom");
digitalWrite(Livingroom,1);
}
}

Just remove * ! because *string refers to the first case in the string ! so *string[0] refers to the first letter in the first case in the string array !

Serial.read() will only read the first byte. You'll have to read the whole string in a loop (and a large enough buffer) and use a compare function to compare the strings.
As an alternative for testing you could use a single byte code - for example 'a', 'b', 'c' and 'd'.
To print the second string in the aray, you can use Serial.println(myStrings[1]).
Here is an example using single chars:
void loop() {
if (Serial.available()) {
int value = Serial.read();
switch (value) {
case 'a':
digitalWrite(Bathroom, 0);
break;
case 'b':
digitalWrite(Bathroom, 1);
break;
case 'c':
digitalWrite(Livingroom, 0);
break;
case 'd':
digitalWrite(Livingroom, 1);
break;
default :
break;
}
if (value >= 'a') { // avoid delaying on newlines
delay(100);
}
}
}

*(myStrings[0]) will get the first (char *) in the array, which points to starting memory location containing bathdim, then you dereference that, using the * which prints the first character, so you get letter b.
Just remove the dereferencing, remove that *
Edit- saw your updated question, the star is not gone, but anyway try using Serial.readString() to read in a string, you are reading in 1 byte at a time

Related

Arduino Code Not Processing Serial Output

I am using a Arduino Uno for an embedded systems course. My assignment is that I have to write a function that implements these specifications. Take an input from the user (‘R’, ‘G’, ‘B’) and display Red, Green or Blue. The function name must be dispColor(), the input must be char a and their is no return. My code is below, however whenever I type in an input I receive no output. Where is the error in my code?
String dispColor(char){
char a = Serial.read();
if (a == "R")
Serial.print("Red");
else if (a == "G")
Serial.print("Green");
else if (a == "B")
Serial.print("Blue");
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
String dispColor();
}
void loop() {
// put your main code here, to run repeatedly:
}
My Updated code
void dispColor(char a){
if(Serial.available()){
a = Serial.read();
if(a == 'R')
Serial.print("Red");
else if(a == 'G')
Serial.print("Green");
else if(a == 'B')
Serial.print("Blue");
}
}
void setup() {
Serial.begin(9600);
Serial.println("Please type in R, G, or B.");
dispColor();
}
void loop() {
}
As says the comment in setup ("// put your setup code here, to run once:", that code will be executed only once, so when you're ready to "type an input", there will not be any code running to read it.
Thus, one thing you'll definitely need to do is move dispColor to loop.
There are a few more mistakes:
You're comparing a char with a String
You should be passing a parameter to dispColor, not reading from within it
You should probably only be calling dispColor if there's input available.
Have a look at https://www.arduino.cc/reference/en/language/functions/communication/serial/read/ to get started!
I figured it out!
My new code
void setup()
{
Serial.begin(9600);
Serial.println("Please type in R, G, or B.");
}
void dispColor(char a)
{
while(!Serial.available());
a = Serial.read();
if(a == 'R')
Serial.println("Red");
else if(a == 'G')
Serial.println("Green");
else if(a == 'B')
Serial.println("Blue");
Serial.print('\n');
}
void loop() {
char a;
dispColor(a);
}

Combined loops not working in Arduino

I have an arduino code which is doing tasks like this:
while (a=='A')
{
//do the task A
}
while (a=='B')
{
//do the task B
}
These loop run correctly when they are run separately. But the problem comes when I try to combine both loops i.e.
void loop ()
{
while (a=='A')
{
//do the task A
}
while (a=='B')
{
//do the task B
}
}
Below is the code in full details:
void loop()
{
////// admin
Serial.println("A or B");
delay(500);
char a = userinput();
delay(500);
while(a== 'A'){
Serial.println("Type Your Starting ID Number...");
while(1 ){
while (Serial.available()==false);
char e = Serial.read();
if(isdigit(e)==false) break;
startid = (startid*10)+(e - 48);
}
if(startid<=endid){
for(pageid=startid; pageid<=endid; pageid++)
{
Serial.print("Your Biometric ID # is ");
Serial.println(pageid);
delay(2000);
fingerenrollment(pageid);
delay(2000);
if(pageid == endid){
Serial.println("......Memory Is Full....");
while(1);
}
}
}
else{
Serial.println("Wrong Entry.......Please Reset Your Device.....");
while(1);
}
}
////// user
while(a=='B'){
lcd.print("WELCOME TO iPoll");
delay(2000);
lcd.clear();
lcd.print("Place Your Thumb");
delay(2000);
lcd.clear();
tempid = '\0';
Serial.println("Place your Thumb For Authentication");
delay(500);
while(true){
ID = fingerauthentication();
delay(500);
if(tempid != '\0') break;
}
delay(100);
resp = userinput();
delay(100);
lcd.clear();
datatrans(ID, resp);
}
}
If you need any more help, I am here. Just comment.
You seem to be stuck in an infinite while loop. Try changing while(a=='A') and while(a=='B') to if(a=='A') and if(a=='B'). The void loop() method in Arduino automatically acts like an infinite while loop, looping through the code within it forever.
while (a == 'A') loop is never ending because you never change the value of a. You need some a = something; somewhere in your code, or do what #Dan12-16 said. The same applies to 'B'.
And a couple of tips to make your code easier to read (in my opinion). Instead of using if (condition == false), you could use if (!condition). Choose while (1) or while (true), but don't mix them (I would choose the second one).

Trouble with loop (arduino)

I am trying to create a small stall at school using and arduino,
the project is to scan items using a barcode scanner enter the price and issue a receipt. the barcode scanner is connected to serial port and keypad and printer are connected via software serial. I am using a 3.5" tv as the display. the items can be identified by the first 3 digits of the barcode. I want to include the item names somewhere in the sketch and match and print them when the string starts with their number.
I have created a sketch with a lot of help from other forum users but the date is being repeatedly printed and not much else is happening. How do I make the date print only once. and also how do I buffer data from serial and software serial before printing.
//#include <TVout.h>
//#include <video_gen.h>
//ARDUINO 1.0 COMPATIBLE ONLY!
//ARDUINO 1.0 COMPATIBLE ONLY!
#include <Time.h>
#include <DS1307RTC.h>
#include <SoftwareSerial.h>
//#include <LiquidCrystal.h>
#include <Thermal.h>
#include <Wire.h>
//TVout TV;
int printer_RX_Pin = 3;
int printer_TX_Pin = 4;
int incomingByte = 0;
Thermal printer(printer_RX_Pin, printer_TX_Pin, 19200);
String readString; // a string to hold incoming data
//SoftwareSerial mySerial(10, 11);
void setup(){
//TV.begin(PAL,120,96);
// TV.select_font(font6x8);
Serial.begin(9600);
//mySerial.begin(9600);
setSyncProvider(RTC.get);
// if (timeStatus() != timeSet )
// Serial.println("Unable to sync with the RTC");
// else
// Serial.println("RTC has set the system time");
//tv.print(scan item) ???
//ITEM SCANNED GETS STORED INTO string.Readstring
//tv print (enter donation Amount)
//INPUT FROM KEYPAD GETS STORED INTO BUFFER1 (KEYPAD IS HOOKED UP TO SOFTWARE SERIAL PINS)
//THEN PRINTER PRINTS TITLE (MAYBE BETTER TO WAIT FOR ALL INPUT BEFORE PRINTING)
printer.justify('C');
//sets text justification (right, left, center) accepts 'L', 'C', 'R'
printer.setSize('L'); // set type size, accepts 'S', 'M', 'L'
printer.println("School Feast "); //print line
printer.setSize('M'); // set type size, accepts 'S', 'M', 'L'
printer.println("My Stall"); //print line
printer.println("My Town");
printer.feed(); //advance one line
printer.println(" My Country");
printer.feed(); //advance one line
}
void serialRead() {
while (Serial.available()) {
delay(10);
if (Serial.available() >0) {
char c = Serial.read();
readString += c;};
}
}
void loop() {
// THEN TIME GETS PRINTED
tmElements_t tm;
if (RTC.read(tm)) {
Serial.print(" ");
print2digits(tm.Hour);
Serial.write(':');
print2digits(tm.Minute);
Serial.write(':');
print2digits(tm.Second);
Serial.print(" ");
Serial.print(tm.Day);
Serial.write('/');
Serial.print(tm.Month);
Serial.write('/');
Serial.print(tmYearToCalendar(tm.Year));
Serial.println();
printer.print(" ");
print2digits(tm.Hour);
printer.write(':');
print2digits(tm.Minute);
printer.write(':');
print2digits(tm.Second);
printer.print(" ");
printer.print(tm.Day);
printer.write('/');
printer.print(tm.Month);
printer.write('/');
printer.print(tmYearToCalendar(tm.Year));
printer.println();
} else {
if (RTC.chipPresent()) {
Serial.println("The DS1307 is stopped. Please run the SetTime");
Serial.println("example to initialize the time and begin running.");
Serial.println();
} else {
Serial.println("DS1307 read error! Please check the circuitry.");
Serial.println();
}
delay(9000);
}
delay(1000);
}
void print2digits(int number) {
if (number >= 0 && number < 10) {
Serial.write('0');
}
Serial.print(number);
if (Serial.available() > 0) {
readString = "";
serialRead();
String Item = readString.substring(0,3);
//THEN ITEM PRINT( IDENTIFY ITEM BY FIRST 3 CHARACTERS OF STRING, HOW??)
Serial.print(Item);
printer.print(Item);
Serial.println();{
//THEN PRINT DONATION AMOUNT(INPUT FROM SOFTWARE SERIAL)
//printer.print(software.serial buffer)
//printer. print("GBP");
//clear display
//tv.clear
}
}
}

Parse the incoming packet

I am receiving a packet like 0xFA5D0D01.
Now i want to parce it like
FA is Header1
5D is Header2
0D is length and
01 is checksum.
const int data_availabe = Serial.available();
I am able to write to serial port but not able to parce it like
if i received FA is then print received Header1
const int data_availabe = Serial.available();
if (data_availabe <= 0)
{
return;
}
const int c = Serial.read();
Serial.print("Receive Status: ");
Serial.println(STATE_NAME[receiveState]);
Serial.print(c, HEX);
Serial.print(" ");
if (isprint(c)) //isprint checks whether it is printable character or not (e.g non printable char = \t)
{
Serial.write(c);
}
Serial.println();
Serial.println(receiveState);
switch (receiveState)
{
case WAITING_FOR_HEADER1:
if (c == HEADER1)
{
receiveState = WAITING_FOR_HEADER2;
}
break;
case WAITING_FOR_HEADER2:
if (c == HEADER2)
{
receiveState = WAITING_FOR_LENGTH;
}
break;
}
Where receiveState is enum changing as we are getting exptected data..
I assume the Arduino is receiving data from USB.
What is the if (data available <= 0) doing? If you want want to read data from the serial port while it is avalaible, you should better do if (Serial.avalaible() > 1) and then Serial.read() inside the {}.
If you initialize a const you won't be able to change its value over time...
What is readString and how is it initialized?
Have you tried to Serial.print(c) to see what's inside?
Once again, it would be easier for us if you could give us more context on why and when this piece of code is running.
EDIT:
#define HEADER_1 0xFA // here you define your headers, etc. You can also use variables.
uint8_t readByte[4]; // your packet is 4 bytes long. each byte is stored in this array.
void setup() {
Serial.begin(9600);
}
void loop() {
while (Serial.avalaible() > 1) { // when there is data avalaible on the serial port
readByte[0] = Serial.read(); // we store the first incomming byte.
delay(10);
if (readByte[0] == HEADER_1) { // and check if that byte is equal to HEADER_1
for (uint8_t i = 1 ; i < 4 ; i++) { // if so we store the 3 last bytes into the array
readByte[i] = Serial.read();
delay(10);
}
}
}
//then you can do what you want with readByte[]... i.e. check if readByte[1] is equal to HEADER_2 and so on :)
}

Sketch that responds to certain commands, how is it done?

Alright I have a half complete Arduino sketch at the moment. Basically the sketch below will blink an LED on a kegboard-mini shield if a string of chars equals *{blink_Flow_A}* However the LED only blinks once with the current sketch loaded on the Arduino. I will like the Arduino to blink repeatedly until the "stop" command is sent to the Arduino. I would eventually like to open a valve, keep it open until the valve receives to the close command then close the valve. The sketch looks like the following,
/*
* kegboard-serial-simple-blink07
* This code is public domain
*
* This sketch sends a receives a multibyte String from the iPhone
* and performs functions on it.
*
* Examples:
* http://arduino.cc/en/Tutorial/SerialEvent
* http://arduino.cc/en/Serial/read
*/
// global variables should be identified with _
// flow_A LED
int led = 4;
// relay_A
const int RELAY_A = A0;
// variables from sketch example
String inputString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
void setup() {
Serial.begin(2400); // open serial port, sets data rate to 2400bps
Serial.println("Power on test");
inputString.reserve(200);
pinMode(RELAY_A, OUTPUT);
}
void open_valve() {
digitalWrite(RELAY_A, HIGH); // turn RELAY_A on
}
void close_valve() {
digitalWrite(RELAY_A, LOW); // turn RELAY_A off
}
void flow_A_blink() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for one second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
void flow_A_blink_stop() {
digitalWrite(led, LOW);
}
void loop() {
// print the string when newline arrives:
if (stringComplete) {
Serial.println(inputString);
// clear the string:
inputString = "";
stringComplete = false;
}
if (inputString == "{blink_Flow_A}") {
flow_A_blink();
}
}
//SerialEvent occurs whenever a new data comes in the
//hardware serial RX. This routine is run between each
//time loop() runs, so using delay inside loop can delay
//response. Multiple bytes of data may be available.
void serialEvent() {
while(Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}
If it makes any difference someone on IRC told me to research state machines scratches head
To blink a Led without blocking the program, i suggest you use Timer (and the TimerOne library). I make a quick sample code :
#include "TimerOne.h" //Include the librart, follow the previous link to download and install.
int LED = 4;
const int RELAY_A = A0;
boolean ledOn;
void setup()
{
pinMode(LED, OUTPUT)
Timer1.initialise(500000) // Initialise timer1 with a 1/2 second (500000µs) period
ledOn = false;
}
void blinkCallback() // Callback function call every 1/2 second when attached to the timer
{
if(ledOn){
digitalWrite(LED,LOW);
ledOn = false;
}
else{
digitalWrite(LED,HIGH);
ledOn = true;
}
}
void open_valve() {
digitalWrite(RELAY_A, HIGH); // turn RELAY_A on
}
void close_valve() {
digitalWrite(RELAY_A, LOW); // turn RELAY_A off
}
void serialEvent() {
while(Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
if (inChar == '\n') {
stringComplete = true;
}
}
}
void loop()
{
// print the string when newline arrives:
if (stringComplete) {
Serial.println(inputString);
// clear the string:
inputString = "";
stringComplete = false;
}
if (inputString == "{blink_Flow_A}") {
Timer1.attachInterupt(blinkCallback); //Start blinking
}
if (inputString == "{stop}") {
Timer1.detachInterrupt(); //Stop blinking
}
if (inputString == "{open_valve}") {
open_valve();
}
if (inputString == "{close_valve}") {
close_valve();
}
}
Note :
Consider putting the tag 'c' or 'java' to have syntax highlighting on the code.
A state machine (at it's simplest - it can be lots more complicated) can be just a set of conditional statements (if/else or switch/case) where you do certain behaviors based on the state of a variable, and also change that variable state. So it can be thought of as a way of handling or progressing through a series of conditions.
So you have the state of your LED/valve - it is either blinking (open) or not blinking (closed). In pseudo code here:
boolean LED_state = false; //init to false/closed
void loop(){
if (checkForCorrectCommand() == true){ //
if (LED_State == false){
open_valve();
LED_State = true;
} else {
close_valve();
LED_State = false;
}
}
}
The blinking LED part should be easy to implement if you get the gist of the code above. The checkForCorrectCommand() bit is a function you write for checking whatever your input is - key, serial, button, etc. It should return a boolean.
Perhaps something like the 'blink without delay' example in the IDE. You check the time and decide to when and how to change the LED/Digital out.
// Variables will change:
int ledState = LOW; // ledState used to set the LED
long previousMillis = 0; // will store last time LED was updated
// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000; // interval at which to blink (milliseconds)
void setup(){
// Your stuff here
}
void loop()
{
// Your stuff here.
// check to see if it's time to blink the LED; that is, if the
// difference between the current time and last time you blinked
// the LED is bigger than the interval at which you want to
// blink the LED.
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
}
Let me offer a suggested sketch with a few changes. Bastyen's idea of using a timer is quite good and makes the code much easier. The approach I would suggest is to have the timer pop forever at a fixed interval (100 milliseconds in my sketch). If the LED should not be blinking it stays off. If the LED should be blinking, it switches from off to on or vice versa each time the timer goes off.
#include "TimerOne.h"
/*
* kegboard-serial-simple-blink07
* This code is public domain
*
* This sketch sends a receives a multibyte String from the iPhone
* and performs functions on it.
*
* Examples:
* http://arduino.cc/en/Tutorial/SerialEvent
* http://arduino.cc/en/Serial/read
*/
// global variables should be identified with _
// flow_A LED
int led = 4;
// relay_A
const int RELAY_A = A0;
// variables from sketch example
String inputString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
boolean shouldBeBlinking = false;
boolean ledOn = false;
void setup() {
Serial.begin(9600); // open serial port, sets data rate to 2400bps
Serial.println("Power on test");
inputString.reserve(200);
pinMode(RELAY_A, OUTPUT);
pinMode(led, OUTPUT);
digitalWrite(led, LOW);
Timer1.initialize(100000);
Timer1.attachInterrupt(timer1Callback);
}
void loop() {
if (!stringComplete)
return;
if (inputString == "{blink_Flow_A}")
flow_A_blink_start();
if (inputString == "{blink_Flow_B}")
flow_A_blink_stop();
inputString = "";
stringComplete = false;
}
void timer1Callback() {
/* If we are not in blinking mode, just make sure the LED is off */
if (!shouldBeBlinking) {
digitalWrite(led, LOW);
ledOn = false;
return;
}
/* Since we are in blinking mode, check the state of the LED. Turn
it off if it is on and vice versa. */
ledOn = (ledOn) ? false : true;
digitalWrite(led, ledOn);
}
void flow_A_blink_start() {
shouldBeBlinking = true;
open_valve();
}
void flow_A_blink_stop() {
shouldBeBlinking = false;
close_valve();
}
void close_valve() {
digitalWrite(RELAY_A, LOW); // turn RELAY_A off
}
void open_valve() {
digitalWrite(RELAY_A, HIGH); // turn RELAY_A on
}
//SerialEvent occurs whenever a new data comes in the
//hardware serial RX. This routine is run between each
//time loop() runs, so using delay inside loop can delay
//response. Multiple bytes of data may be available.
void serialEvent() {
if (stringComplete)
return;
while(Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString unless it is a newline
if (inChar != '\n')
inputString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
else {
stringComplete = true;
}
}
}
A few notes:
The setup function establishes the timer with a 100 millisecond interval and attaches the callback routine. Based on my testing, this only needs to be done once.
The main loop just ignores everything unless an input string is complete. If an input string is ready, then the input string is checked for two known values and the appropriate steps are taken. The input string is then discarded.
The timer callback routine forces the LED off, if we are not in blinking mode. Otherwise, it just toggles the state of the LED.
The flow on and flow off routines set the blinking state as need be and control the valve
The serial event routine has two changes. First, input is ignored (and kept in the buffer) if an input string is already complete. This will preserve commands that are being sent to the Arduino while the current command is being processed. Second, the newline character is not added to the input string. This makes checking the input string slightly easier.

Resources