Arduino LED blinking -> need some clarification and explanation - arduino

So, me and my friend were assigned a task:
When 'A' is given as input to serial monitor, the led must blink once.
When 'B' is given a input, the led must blink continuously.
And we successfully finished the task using the code attached.
char a;
void setup()
{
pinMode(13, OUTPUT);
Serial.begin(9600);
}
void loop()
{
if(Serial.available())
{
a= Serial.read();
if(a == 'A')
{
digitalWrite(13, HIGH);
delay(1000); // Wait for 1000 millisecond(s)
digitalWrite(13, LOW);
delay(1000); // Wait for 1000 millisecond(s)
}
}
if(a=='B')
{
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
delay(500);
}
}
But then we have a doubt to be clarified.
Both the conditions are given inside loop , but the one inside the if(Serial.available()) condition makes the led blink once while the condition outside the if(Serial.available()) makes the led blink continuously. Why??
Note that the code is the same for if(a=='A') and if(a=='B').
I really need an explanation for this question.

if(a=='B') will be executed continuously since it stays true until new input is received and it is in loop that is being called repeatedly.
if(a == 'A') is only evaluated once after a new character is received. If there is no character it is never checked again.
loop is called repeatedly regardless of whether there is new input available. variable a have global scope so it will not change between calls. It will contain the last received input.

In your code, the character held by a is only changed when Serial.available() returns a non-zero value, which only happens when you press a key. In the API Reference, we can see that Serial.available() actually returns the number of characters available, so the recommended usage is if (Serial.available() > 0).
To get the intended behavior (if I've understood your problem correctly) you should move the if 'B' part to within the if available() part. Something like this
void loop()
{
if (Serial.available() > 0)
{
a = Serial.read();
if (a == 'A')
{
digitalWrite(13, HIGH);
delay(1000); // Wait for 1000 millisecond(s)
digitalWrite(13, LOW);
delay(1000); // Wait for 1000 millisecond(s)
}
else if (a == 'B')
{
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
delay(500);
}
}
}

When you enter something in the Serial Monitor and press enter, then Serial.available() returns a true, Then you read the buffer, in this case it is either A or B, and then you assign the variable a to the character that is read.
You should note that Serial.available() returns true only when you press enter, so when yo press enter to submit your input, the code under the if condition is executed, and that's why the led blinks only once, because after that Serial.available() returns false.
Since you are assigned the variable c under the Serial.available() condition, it remains whatever is read in the serial monitor. that's why when you enter B, c == 'B' is always true and the led blinks continuously.

Related

Why is my Arduino sending a message infinitely?

I can't figure out why my Arduino is infinitely sending the same message to the Serial Monitor.
The goal of this project is to monitor and control a basic switching algorithm to redirect power through a power "grid" when a fault is detected in one particular branch to minimize the number of customers that are affected during a power outage. Neither of the two modules (each monitoring its own branch in the "grid") are designed to be a master or client. They will each receive the exact same code ("sketch"). Whoever sees a fault first will start a dialogue and begin the algorithm for redirecting power.
The basic premise is to have one module detect a fault and ask its neighbor if it also has a fault. If it doesn't, it will ask if it is okay to redirect power to that module's branch from the neighbor's branch. The fault-detecting module will send the neighboring module its last known power flow information. The neighbor will determine whether or not its "transmission lines" can handle the increased power flow, and then redirect power (via a relay) accordingly.
However, I can't get passed the first message. Once the "fault" is detected, the fault-detecting module sends its message infinitely. What I need is for it to send a message, then wait for a response, and then react accordingly.
Serial Monitor Message Display
Below is the Fault-Detecting Module portion of code.
I am new to Arduino and StackOverflow. I apologize if I am breaking any of the community's norms or guidelines. But, I can't find any forums that explicitly address this issue and none of the "fixes" have resolved the problem.
Thanks
int StatusPin = 13; //Assigns Pin 13 to be called "StatusPin"
int Relay = 12; //Relay Signal Pin
int Feeder = 11; //Feeder Control Switch Signal Pin
int readPin = A0; //Assigns Pin A) to be called "readPin"
int msg = 0; //Used for case declaration
//Default = 0
//Yes = 1
//No = 2
//Are You OK? = 3
//Switching Possible? = 4
int Pcheck = 0; //Used for Power Calculation
float val = 0; //Creates an empty variable to store future readings
float volts = 0; //Same as above
char statTX = "Good"; //Current Status for this module
void setup() {
char statTX = "Good"; //Default Status for this module
pinMode(StatusPin, OUTPUT);
pinMode(Relay, OUTPUT);
pinMode(Feeder, OUTPUT);
Serial.begin(9600);
}
void loop() {
val = analogRead(readPin); //Stores the input value from the A0 pin into a variable
volts = (val/1024)*5; //Converts ADC reading to volts
digitalWrite(Feeder, LOW); //Feeder Switch is Default OPEN
if (val <= 676){
digitalWrite(StatusPin, HIGH); //Green light status turns on when greater than 3.3V
digitalWrite(Relay, HIGH); //Breaker switch is closed
}
//Transmission Code for Fault Detection Side
else{
statTX = "Fault";
Serial.println("Fault"); //Sent Fault Status Message
digitalWrite(Relay, LOW); //Breaker switch is opened
digitalWrite(StatusPin, LOW); //Green light status turns off when greater than 3.3V
Serial.write(3); //Send "Are You Okay?" message
if (Serial.available() == 0){ //Creates a pause to wait for a response
}
else{
msg = Serial.read();
if (msg == 1) {
statTX = "Isolated"; //Declares fault isolated
Serial.println("Isolated");
Serial.write(4); //Send Message to Request Switch
if (Serial.available() == 0){ //Creates a pause to wait for a response
}
else{
msg = Serial.read();
if (msg == 1){
Serial.write(20); //Sends tentative current draw
if (Serial.available() == 0){
}
else {
msg = Serial.read();
if (msg == 1 && val < 676){
statTX = "SystemRestored";
Serial.println("SystemRestored");
digitalWrite(StatusPin, HIGH); //Green light status turns on when greater than 3.3V
}
else {
statTX = "Failure";
Serial.println("Failure");
}
}
}
else {
statTX = "Failure";
Serial.println("Failure");
}
}
}
}
}
Thing is, that the void loop() {...} procedure is called repeatedly. So if none of the conditions have changed, the output stay the same.
In your case, the
if (val <= 676){...
is not taken. And so, the else block executes the following commands and are printed to serial.:
Serial.println("Fault"); //Sent Fault Status Message
...
Serial.write(3); //Send "Are You Okay?" message
This is not visible in your output image, but I guess that the □ (U+25A1) at the beginning of the line is from a preceding iteration - from Serial.write(3);. But this cannot be confirmed by the output image given. And if if (Serial.available() == 0){... will never be taken, the above commands will be executed in a permanent loop.
And this output repeats infinitely, because the void loop() function does not execute any other code paths, repeatedly.

Having both manual and automatic functions for an led

So I have come to a problem where I can not get out of a loop after I'm in it. My project is to have two functions, one for manual and another for automatic which will run forever, but I want that when I am in automatic, I will be able to get out by clicking the manual button on my phone. I don't know if that makes sense, but I really need help.
//Program to control LED (ON/OFF) from ESP32 using Serial Bluetooth
#include <Arduino.h>
#include <BluetoothSerial.h> //Header File for Serial Bluetooth, will be added by default into Arduino
BluetoothSerial ESP_BT; //Object for Bluetooth
int incoming;
int yellow_led = 13;
void setup() {
Serial.begin(9600); //Start Serial monitor in 9600
ESP_BT.begin("ESP32_LED_Control"); //Name of your Bluetooth Signal
Serial.println("Bluetooth Device is Ready to Pair");
pinMode (yellow_led, OUTPUT);//Specify that LED pin is output
}
void automatic()
{
while (incoming != 51)
{
digitalWrite(yellow_led, HIGH);
ESP_BT.println("LED turned ON");
delay(1000);
digitalWrite(yellow_led, LOW);
ESP_BT.println("LED turned OFF");
delay(1000);
}
}
void manual()
{
if (incoming == 49)
{
digitalWrite(yellow_led, HIGH);
ESP_BT.println("LED turned ON");
}
else if(incoming == 48)
{
digitalWrite(yellow_led, LOW);
ESP_BT.println("LED turned OFF");
}
}
void loop() {
if (ESP_BT.available()) //Check if we receive anything from Bluetooth
{
incoming = ESP_BT.read(); //Read what we recevive
Serial.print("Received:"); Serial.println(incoming);
if (incoming == 51) //#3
{
ESP_BT.println("In Manual Mode");
manual();
}
else if (incoming == 52) //#4
{
ESP_BT.println("In Automatic Mode");
automatic();
}
}
delay(20);
}
The while loop in the automatic function is unnecessary. You're already looping infinitely within loop() so that should be enough. Adding another loop, even though at first may seem like it will break, turns out to be an infinite loop. I'll get to that in a second.
So all you need to do is get rid of the while loop and it should work. However, this works only if you are guaranteed to have an incoming value for each time in the loop, which is what seems like from your code.
Another problem I see here is that if you enter say manual(), there is nothing really that changes the value of incoming, you're bound to have 51 as you're reusing the previous value and nothing no desired code path will be triggered.
Same also applies to automatic(), I hope you can see how that loop becomes infinite because of this.
So you also need something on the following lines.
void manual()
{
if (!ESP_BT.available())
return;
incoming = ESP_BT.read();
if (incoming == 49)
{
digitalWrite(yellow_led, HIGH);
ESP_BT.println("LED turned ON");
}
else if(incoming == 48)
{
digitalWrite(yellow_led, LOW);
ESP_BT.println("LED turned OFF");
}
}
Lastly, need help lol, please and thank you may not be descriptive enough for anybody to help with your problem, please go through, how to ask a good question for the next time you're posting.

How to control an led from Thingspeak server using SIM900A and Arduino?

I am trying to control a LED from Thingspeak server by using the GSM module.
The data received is successfully being printed on serial monitor(which is '1' as last updated) but when I am trying to assign that data to a variable so as to control the inbuilt LED of Arduino, nothing happens.
#include <SoftwareSerial.h>
SoftwareSerial SIM900A(10, 11);
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
SIM900A.begin(9600);
Serial.begin(9600);
while (!Serial)
;
Serial.println("Arduino is ready");
SIM900A.begin(9600);
Serial.println("SIM900A started at 9600");
delay(1000);
Serial.println("Setup Complete");
}
void loop()
{
SIM900A.println("AT");
delay(1000);
ShowSerialData();
SIM900A.println("AT+CIPSHUT");
delay(2000);
ShowSerialData();
SIM900A.println("AT+CIPMUX=0");
delay(2000);
ShowSerialData();
SIM900A.println("AT+CGATT=1");
delay(5000);
SIM900A.println("AT+CSTT=\"INTERNET\",\"\",\"\"");
delay(4000);
SIM900A.println("AT+CIICR");
delay(3000);
ShowSerialData();
SIM900A.println("AT+CIFSR");
delay(5000);
ShowSerialData();
SIM900A.println("AT+CIPSTART=\"TCP\",\"184.106.153.149\",\"80\"");
delay(4000);
ShowSerialData();
SIM900A.println("AT+CIPSEND");
delay(4000);
SIM900A.print("GET /channels/798173/fields/1/last");
SIM900A.print("\r\n\x1A");
ShowSerialData();
char led = SIM900A.read();
Serial.print(led);
if (led == '1')
{
digitalWrite(LED_BUILTIN, HIGH);
}
else if (led == '0')
{
digitalWrite(LED_BUILTIN, LOW);
}
delay(8000);
}
void ShowSerialData()
{
while (SIM900A.available() != 0)
Serial.print(char(SIM900A.read()));
}
Last portion of the output from the serial monitor:
CONNECT OK
AT+CIPSEND
> ⸮GET /channels/798173/fields/1/last
SEND OK
1
As pointed out by #Saurabh P Bhandari, you cannot read the same data from the serial twice, thus you'd need to read the data in a variable in the first place if you wish to use it.
String getSerialData(){
String buffer="";
while (SIM900A.available() ){
char c = SIM900A.read();
buffer+=c;
}
return buffer;
}
Then you can use String led = getSerialData() to populate led with the buffer.
Here, you need to beware that the function getSerialData would return anything present on the buffer and would look something like:
GET /channels/798173/fields/1/last
SEND
HTTP RESPONSE
It appears that you're only interested in HTTP RESPONSE, thus you can update your conditionals to be
if(led.endsWith("1"))
...
else if(led.endsWith("0"))
From what I have understood so far, in this snippet
SIM900A.print("GET /channels/798173/fields/1/last");
SIM900A.print("\r\n\x1A");
ShowSerialData();
ShowSerialData() is printing the output which is '1'. Then immediately your are reading data into the variable led. Since, the actual data received is being printed already from ShowSerialData(), the next time you call SIM900A.read() will return either nothing or next set of data being sent by your module.
You are likely getting rate limited because you are hitting ThingSpeak servers too frequently. You can only update a channel once every 15s with a free account. Obviously, it makes no sense to ask for a value faster than it can be updated, i.e., once every 15s with a free account.
Consider putting some required delays in your code to ensure your device is not blacklisted for abuse of terms.

How to Make Program Stop after Number of Iterations

So, I have my program here, I am trying to make a program that, we manually pull the wire out and place it back, each time I pull it out, it is 1 iteration and placing it back in is 1 iteration. Whenever it is connected to the port the external LED is dark, when it is pulled out, the external LED is bright. I should be able to do this for 10 iterations and stop once I get there.
The problem is, when I include the while(true); statement in, my external LED does not work, but without the statement in there, the program runs the way I want except that it does not stop working after 10 iterations, any help is appreciated!
#include<EEPROM.h>
const int LED = 12;
const int SWITCH = 4;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(LED, OUTPUT); //LED is always outputting information
pinMode(LED_BUILTIN, OUTPUT); //Built in LED is always outputting information
pinMode(SWITCH, INPUT_PULLUP); //Switch inputs value when in/out of ground
}
void loop() {
// put your main code here, to run repeatedly:
int addr = 0; //Declaring variables
int count = 0;
int seconds;
if (digitalRead(SWITCH) == LOW) { //If wire starts in ground, record values
Serial.println("----Recording----");
while (count <= 10) { //While count value is less than or equal to 10
if (digitalRead(SWITCH) == LOW) { //When wire is connected to 4
count = count + 1; //Add one to count in each iteration
digitalWrite(LED, LOW); //LED light is off in this position
delay(50); //Checks switch state every 0.05 seconds
}
else if (digitalRead(SWITCH) == HIGH) { //When wire isnt connected to 4
count = count + 1; //Add one to count in each iteration
digitalWrite(LED, HIGH); //LED light is on in this position
delay(50); //Checks switch state every 0.05 seconds
}
while (true);
}
}
}
Why it's not working? Let's rewrite your code a little:
while (count <= 10) {
count = count + 1;
digitalWrite(LED, digitalRead(SWITCH));
delay(50);
while (true); // aaand kill it
}
I'm ommiting the race condition if the first digital read returns HIGH and then the second returns LOW (it wouldn't wait for 50ms to stop)
I'd expect something like counting on pin change or so:
while (count <= 10) {
byte = digitalRead(SWITCH);
if (byte != digitalRead(LED))
{
count = count + 1;
digitalWrite(LED, byte);
}
delay(50);
}
while (true); // aaand kill it

Unable to store stream data in variable in Arduino programming

I'm unable to store the serial.port value in a variable. I want to send a message from Android telnet app, on and off. If on comes I want to print fan on, if off comes I want to print off. I'm able to print on and off while I'm statically fixing value. I'm unable to store the stream in a variable.
String stringOne;
void setup() {
digitalWrite(13, LOW);
// 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
}
// send an intro:
Serial.println("\n\nString substring():");
Serial.println();
pinMode(13,OUTPUT);
}
void loop() {
digitalWrite(13,LOW);
// Set up a String:
stringOne ="+IPD 0,14 :ON";
int length = stringOne.length();
Serial.println(stringOne.length());
Serial.println(stringOne);
if (Serial.available() > 0) {
// substring(index) looks for the substring from the index position to the end:
if (stringOne.substring(length-2,length) == "ON") {
Serial.println("FAN ON");
digitalWrite(13,HIGH);
// delay(2000);
}
if (stringOne.substring(length-3,length) == "OFF") {
Serial.println("FAN OFF");
digitalWrite(13,LOW);
// delay(2000);
}
}
// you can also look for a substring in the middle of a string:
// do nothing while true:
while (true);
}
Well, while editing your question, I couldnt help noticing that infinite loop at the end of your code.
// do nothing while true:
while(true)
In this case, even if your code was all right, you cant expect to get next data.
void loop --> Remember it is itself a infinite loop
update 1:
your logic to use the serial port is wrong;
Remember, serial port only recieves a single character at a time.
if you send "hello" from pc, at the other end, arduino will recieve h, e, l, l, o
The trick is to collect all letters into a array. and then use our logic in it.
char commandbuffer[20]; //an array to hold our characters
int i=0;
if (Serial.available() > 0) {
while( Serial.available() >0) { //read until all data we send arrives
char c = Serial.read();
commandbuffer[i]= c; //we are actually storing it one by one
i++;
}
}
commandbuffer[i]='\n';
for(int j = 0; j<i; j++){
Serial.print(commandbuffer[j]);// and show it one by one too
}
now when you send "hello", it will print hello back. I hope this give you some idea. Happy coding.

Resources