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);
}
Related
I am currently working on a project that will be used to test whether an instrument is within tolerance or not. My test equipment will put the DUT (Device Under Test) into a "Test Mode" where it will repeatedly send a string of data every 200ms. I want to receive that data, check is is within tolerance and give it a pass or fail.
My code so far (I've edited a few things out like .h files and some work related bits!):
void GetData();
void CheckData();
char Data[100];
int deviceId;
float a;
float b;
float c;
void ParseString(const char* stringValue)
{
char* token = NULL;
int tokenPlace = 0;
token = strtok((char *) stringValue, ",");
while (token != NULL) {
switch (tokenPlace) {
case 0:
deviceId = atoi(token);
break;
case 1:
a= ((float)atoi(token)) / 10.0f;
break;
case 2:
b= ((float)atoi(token)) / 100.0f;
break;
case 3:
c= ((float)atoi(token)) / 10.0f;
break;
}
tokenPlace++;
token = strtok(NULL, ",");
}
}
void GetData()
{
int x = UART.scanf("%s,",Data);
ParseString(Data);
if (x !=0) {
UART.printf("Device ID = %i\n\r", deviceId);
UART.printf("a= %.1f\n\r", a);
UART.printf("s= %.2f\n\r", b);
UART.printf("c= %.1f\n\n\r", c);
}
if (deviceId <= 2) {
CheckData();
} else {
pc.printf("Device ID not recognised\n\n\r");
}
}
void CheckData()
{
if (a >= 49.9f && a< = 50.1f) {
pc.printf("a Pass\n\r");
} else {
pc.printf("a Fail\n\r");
}
if (b >= 2.08f && b <= 2.12f) {
pc.printf("b Pass\n\r");
} else {
pc.printf("b Fail\n\r");
}
if (c >= 20.0f && c <= 25.0f) {
pc.printf("c Pass\n\n\r");
} else {
pc.printf("c Fail\n\n\r");
}
if (deviceId == 0) {
(routine1);
} else if (deviceId == 1) {
(routine2);
} else if (deviceId == 2) {
(Routine3);
}
}
int main()
{
while(1) {
if(START == 0) {
wait(0.1);
GetData();
}
}
}
And this works absolutely fine. I am only printing the results to a serial terminal so I can check the data is correct to make sure it is passing and failing correctly.
My issue is every now and then the START button happens to be pressed during the time the string is sent and the data can be corrupt, so the deviceId fails and it will say not recognised. This means I then have to press the start button again and have another go. A the moment, it's a rare occurrence but I'd like to get rid of it if possible. I have tried adding a special character at the beginning of the string but this again gets missed sometimes.
Ideally, when the start button is pressed, I would like it to wait for this special character so it knows it is at the beginning of the string, then the data would be read correctly, but I am unsure how to go about it.
I have been unsuccessful in my attempts so far but I have a feeling I am overthinking it and there is a nice easy way to do it. Probably been staring at it too long now!
My microcontroller is STM32F103RB and I am using the STM Nucleo with the mBed IDE as it's easy and convenient to test the code while I work on it.
You can use ParseString to return a status indicating whether a complete string is read or not.
int ParseString(const char* stringValue)
{
/* ... your original code ... */
/* String is complete if 4 tokens are read */
return (tokenPlace == 4);
}
Then in GetData use the ParseString return value to determine whether to skip the string or not.
void GetData()
{
int x = UART.scanf("%s,",Data);
int result = ParseString(Data);
if (!result) {
/* Did not get complete string - just skip processing */
return;
}
/* ... the rest of your original code ... */
}
I've been trying to achieve serial communication between my arduino-based project and my pc ,i need to send commands to arduino over serial and use "if and else" to call desired function (in parseMessage() function).
I can't use delay() since I'm using interrupts for multiplexing and bit-angle modulation so i had to do serial communication another way around, this is closest I've got to succeess but still I'm getting character skips and unstability in general. and as you know coding is all great except for when you don't know what's wrong with your code, so help me please gods of the internet! ;)
The reason I'm using '#' as end of the string declearation is that I can't be sure that all characters of my command sent to arduino is there when Serial.read() asks for it, there might be more on the way and since atmega328 is faster than serial port Serial.available() might actually return -1 in middle of transmission.
ps : oh, and I can't use String class, It's very expensive, this atmega328 is already sweating under 8x8 RGBLED multiplexing and 4bit-angle modulation and he is gonna have to do even more in future.
ps : and I'm still learning English so pardon me if there is something wrong with the grammer I'm using.
void setup() {
Serial.begin(9600);
}
bool dataRTP = false; // data ready to parse
void loop() {
readSerial();
}
char message[64];
int index = 0;
void readSerial() {
if (Serial.available() > 0)
while (Serial.available() > 0)
if (Serial.peek() != '#') // i'm using '#' as end of string declearation.
message[index++] = Serial.read();
else {
message[index++] = '\n';
dataRTP = true;
break;
}
while (Serial.read() != -1) {} // flushing any possible characters off of
if (dataRTP) // UARTS buffer.
parseMessage();
}
void parseMessage() { // just testing here, actual code would be like :
Serial.print(message); // if (!strcmp(message, "this expression"))
index = 0; // callthisfunction();
dataRTP = false; // else ... etc
}
Just managed to fix this code, seems flushing data off of serial UART wasn't a good idea after all. It's all solved. Here's how code looks now:
void setup() {
Serial.begin(9600);
}
bool dataRTP = false;
void loop() {
readSerial();
}
char message[64];
int index = 0;
void readSerial() {
if (Serial.available() > 0)
while (Serial.available() > 0)
if (Serial.peek() == '#') {
message[index++] = Serial.read();
message[index++] = '\0';
dataRTP = true;
break;
}
else
message[index++] = Serial.read();
if (dataRTP)
parseMessage();
}
void parseMessage() {
Serial.println(message);
index = 0;
dataRTP = false;
}
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).
I am trying to create beep sound from characters in the string.
Here is the code:
/*
* Buzzer connected to Arduino uno digital pin 13
* Switch connected to digital pin 2
*/
#include <avr/io.h>
#include <util/delay.h>
const int TBEEP = 1000;
const int TBEEEEP = 3500;
const int TGAP = 500;
const int TGAPLETTER = 2000;
int portb = 0x20;
void beep() {
PORTB = ~portb; _delay_ms(TGAP);
PORTB = portb; _delay_ms(TBEEP);
PORTB = ~portb; _delay_ms(TGAP);
}
void beeeep() {
PORTB = ~portb; _delay_ms(TGAP);
PORTB = portb; _delay_ms(TBEEEEP);
PORTB = ~portb; _delay_ms(TGAP);
}
void gapLetter() {
PORTB = ~portb; _delay_ms(TGAPLETTER);
}
void morse_S() {
beep(); beep(); beep();
gapLetter();
}
void morse_M() {
beeeep(); beeeep();
gapLetter();
}
void morse_SMS() {
morse_S(); morse_M(); morse_S();
}
void morse(char theString[]) {
for (int i = 0; theString[i] != '\0'; i++)
{
if(&theString[i] == "S")
morse_S();
else if(&theString[i] == "M")
morse_M();
}
}
int main (void)
{
DDRB = 0xFF;
DDRD = 0x00;
PORTD = 0x04;
while (1) {
if (PIND & 0x04) {
PORTB = ~0x20;
} else {
//morse_SMS(); // it works
morse("SMS"); // this one doesnt work like morse_SMS() PLEASE HELP!
}
}
return 0;
}
In function void morse(char theString[]) {...}, I want to produce beep sound from every character in the string "SMS". Unfortunately, only the last character can make it.
I am using Atmel Studio 6. When I build solution (F7) there is no error but warning which I dont understand (sorry for being such a total noob)
comparison with string literal results in unspecified behavior [-Waddress]
How to force every character to beep one after another?
First of all,
const int TBEEP = 1000;
const int TBEEEEP = 3500;
These made my day. :)
Apart from that, you should really get a good beginner C book. You can't compare strings using the == operator, because that compares pointers, not contents. If you want to compare strings, use the strcmp() function from the C standard library.
But: in your case, you don't want to compare strings. You want to compare characters. And that can be done with ==, just dereference the character pointer to obtain the actual character, and compare it with a character literal, not with a string literal:
if (theString[i] == 'S')
morse_S();
else if (theString[i] == 'M')
morse_M();
Oh, and probably you want to avoid that enormous chained if...else if...else monster. Assuming UTF-8 or at least ASCII encoding, where the character codes of English letters are in alphabetical order:
void (*morse_funcs[26])();
morse_funcs[0] = morse_A;
morse_funcs[1] = morse_B;
// ...
morse_funcs[25] = morse_Z;
// ...
void morse(const char *s)
{
while (*s)
morse_funcs[tolower(*s++) - 'a']();
}
Also, notice how I changed char * into const char *. If you don't modify a string, tell the compiler that you don't intend to modify it, so you can safely pass in string literals as well.
Even better: don't use a table of function pointers, but a table of Morse codes. Like this:
const char *mcodes[26] = {
".-", // 'a'
"-...", // 'b'
// etc...
"--.." // 'z'
};
void do_morse(const char *code)
{
while (*code)
if (*code++ == '-')
beeeep();
else
beep();
}
void morse(const char *s)
{
while (*s)
do_morse(mcodes[tolower(*s++) - 'a']);
}
Try this:
void morse(char theString[]) {
for (int i = 0; theString[i] != '\0'; i++)
{
if(theString[i] == 'S')
morse_S();
else if(theString[i] == 'M')
morse_M();
}
}
update
I'm using pic 18F4550 with microchip v8.63 and C compiler.
I'm trying to make a color sensor. When a led burns a whant to go for example methode red.
In OOP is that simple to go to other methods, but how can you do that in C for microchip?
void main(void)
{
my code here....
// Leds are connected here.
if(PORTBbits.RB4 == 0) { //red
LATDbits.LATD0 = 1;
}
else if(PORTBbits.RB5 == 0) { //green
LATDbits.LATD1 = 1;
}
else if(PORTBbits.RB6 == 0) { //blue
LATDbits.LATD2 = 1;
}
// LDR is connected here.
//
if(PORTAbits.RA0 == 1) {
if(PORTBbits.RB4 == 0) {
int red = PORTBbits.RB1; // test.
colorRed();
}
else if(PORTBbits.RB5 == 0) {
int green = PORTBbits.RB1;
colorGreen();
}
else if(PORTBbits.RB6 == 0) {
int blue = PORTBbits.RB1;
colorBlue();
}
}
}
void colorRed(void)
{
LATDbits.LATD0 = 0;
// other code here
}
void colorGreen(void)
{
LATDbits.LATD1 = 0;
}
void colorGreen(void)
{
LATDbits.LATD2 = 0;
}
These are the errors:
..\code\main.c:56:Warning [2058] call of function without prototype
..\code\main.c:60:Warning [2058] call of function without prototype
..\code\main.c:64:Warning [2058] call of function without prototype
..\code\main.c:69:Error [1109] type mismatch in redeclaration of 'colorRed'
..\code\main.c:74:Error [1109] type mismatch in redeclaration of 'colorGreen'
..\code\main.c:79:Error [1504] redefinition of 'colorGreen'
You simply need to add forward declarations ("prototypes") for the functions before the definition of main.
void colorRed(void);
void colorGreen(void);
void colorBlue(void);
Without these, the compiler assumes a function type of int colorRed(), where int mismatches with void and () mismatches with (void).
Also, as I mentioned in the comments, main should implement an endless loop which checks the chip's inputs and modifies the outputs.