#include <stdio.h>
#define LED 13
void setup() {
pinMode(LED, OUTPUT);
Serial.begin(9600);
}
void loop() {
if (Serial.available() == 4) {
char command[5];
for (int i = 0; i < 4; i++) command[i] = Serial.read();
command[4] = '\0';
Serial.println(command);
if (strcmp(command, "AAAA") == 0) {
digitalWrite(LED, HIGH);
Serial.println("LED13 is ON");
} else if (strcmp(command, "BBBB") == 0) {
digitalWrite(LED, LOW);
Serial.println("LED13 is OFF");
}
}
}
I have that code, that reads 4 characters long strings. However, I need it to ignore any string that is not 4 characters long.
So, imagine this input:
AAAA
BBBB
BBB
AAAA
Right now, it reads {"AAAA", "BBBB", "BBBA"}.
I need it to read {"AAAA", "BBBB", "AAAA"}.
Any idea? Thank you.
You can check the duration time of inter-character delay. Set a timeout, such as 100ms. When there is no more data received after the specified timeout, that means the whole string is transferred completely. Then you can check the length of the string and execute your application logic.
Related
I want my Arduino to light up the LED if he reads "on" in the Serial Port.
At Serial.print(serialData); it prints out what he reads but at if (serialData == "on") it wont work.
int led1 = 9;
int led2 = 6;
String serialData;
void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
Serial.begin(9600);
Serial.setTimeout(10);
}
void loop() {
if (Serial.available() > 0){
serialData = Serial.readString();
Serial.print(serialData);
if (serialData == "on"){
analogWrite(led1, 255);
}
if (serialData == "off"){
analogWrite(led1, 0);
}
}
}
Anybody know, what I'm doing wrong?
There are two issues in your code:
The timeout is set to 10ms. In 10ms, you can at best enter a single character. readString() will return after a single character and the read string will likely be "o", "n", "f".
When you hit the RETURN key, a carriage return and a line feed character are also transmitted ("\r\n").
The solution is to increase the timeout considerably and to use readStringUntil() to read until the newline character is discovered. This is the indication that a full word (or command) has been entered.
Additionally, the carriage return and line feed need to be trimmed off.
#include <Arduino.h>
int led1 = 9;
int led2 = 6;
String serialData;
void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
Serial.begin(9600);
Serial.setTimeout(2000);
}
void loop() {
if (Serial.available() > 0){
serialData = Serial.readStringUntil('\n');
serialData.trim();
Serial.println(serialData);
if (serialData == "on"){
analogWrite(led1, 255);
}
if (serialData == "off"){
analogWrite(led1, 0);
}
}
}
I am new to this shift register. So i created a online simulation of the shift register that hook up to 8 LEDs, the ol' 8bit translate to 8 LED experiment. My design is that when i entered a character like "a" into the serial monitor, it will show in the result in code like 100000, and it should shown in the LEDs too(the sixth LED should light up).
char character;
byte input = 0b01;
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
byte input = 0b01;
if (Serial.available() > 0) {
character = Serial.read();
if (character == 'a') {
Serial.print("character received: ");
Serial.println(character);
for (int i = 0; i < 5; i++) {
updateShiftRegister(input);
input = input << 1;
delay(100);
}
Serial.print("Input: ");
Serial.print(input, BIN);
Serial.println();
} else {
Serial.print("Please retry.\n");
}
}
}
void updateShiftRegister(byte input) {
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, input);
digitalWrite(latchPin, HIGH);
}
Problem is when i run the thing, the result is alright but the shift register in the simulation is wack. Every LEDs turn on,
I found the shiftout function is main cause of this, any idea why it is causing every LED to light up?
I would like to create an Arduino program that receives (via serial) only two commands: "1" and "2".
Through these commands, I would like Arduino to operate a stepper motor like this:
If I write "1" on the serial, the motor must move clockwise
If I write "2" on the serial, the motor must move counterclockwise
I have already written a code that only works halfway:
#include <Stepper.h>
const int stepsPerRevolution = 1500;
int incomingByte;
Stepper myStepper(stepsPerRevolution, 11, 9, 10, 8);
void setup() {
myStepper.setSpeed(20);
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
Serial.print("I received: ");
Serial.println(incomingByte);
if (incomingByte = "1") {
Serial.println("Moving clockwise...");
myStepper.step(stepsPerRevolution);
delay(500);
}
if (incomingByte = "2") {
Serial.println("Moving counterclockwise...");
myStepper.step(-stepsPerRevolution);
delay(500);
}
}
}
When active, the program waits for the commands on the serial port and manages to read them. The problem is that in both cases (1 and 2) the motor moves first clockwise and then subsequently anticlockwise and it is not the result I would like to achieve.
Can you give me a hand in this endeavor?
Use comparison operation instead of assignment operator like so.Double quote around 1 is not required since the variable is int datatype. Use an else command after the first if statement so that only one of the commands will operate.
const int stepsPerRevolution = 1500;
int incomingByte;
Stepper myStepper(stepsPerRevolution, 11, 9, 10, 8);
void setup() {
myStepper.setSpeed(20);
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
Serial.print("I received: ");
Serial.println(incomingByte);
if (incomingByte == 49) {
Serial.println("Moving clockwise...");
myStepper.step(stepsPerRevolution);
delay(500);
}
else
if (incomingByte == 50) {
Serial.println("Moving counterclockwise...");
myStepper.step(-stepsPerRevolution);
delay(500);
}
}
}
Ok, here is the final code; all working!
#include <Stepper.h>
const int stepsPerRevolution = 1500;
int incomingByte;
Stepper myStepper(stepsPerRevolution, 11, 9, 10, 8);
void setup() {
myStepper.setSpeed(20);
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
Serial.print("I received: ");
Serial.println(incomingByte);
if (incomingByte == 49) {
Serial.println("Moving clockwise...");
myStepper.step(stepsPerRevolution);
delay(500);
}
else
if (incomingByte == 50) {
Serial.println("Moving counterclockwise...");
myStepper.step(-stepsPerRevolution);
delay(500);
}
}
}
I'm trying to take an input from the Arduino serial connection and write that to a file on the IoT2020. The code I'm using testing with is bellow.
The issue I'm having is that the code does not appear to recognize that there is an input and nothing imputed from the serial appears in the file. I even added an LED "notification" to turn on when a new line is detected in the interrupt but it never turns on. This would mean there is something intrinsically flawed in my code. Any help would be great.
//File handle creation
FILE *testFile;
String inputString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
char buff[400];
void setup()
{
// sleep(3);
Serial.begin(115200);
pinMode(6, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
// reserve 200 bytes for the inputString:
inputString.reserve(400);
// Create files
system("touch /media/test.txt");
}
void loop()
{
digitalWrite(6, LOW);
delay(1000);
testFile = fopen("/media/test.txt", "a+");
fprintf(testFile,"This is a great test that has just started \n\r");
fclose(testFile);
while(1)
{
digitalWrite(6, HIGH);
// digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(6, LOW);
// digitalWrite(LED_BUILTIN, LOW);
delay(5000);
if (stringComplete) {
// clear the string:
inputString = "";
stringComplete = false;
testFile = fopen("/media/test.txt", "a+");
//if the file opened okay, write to it:
if (testFile)
{
fprintf(testFile,"This is a great test");
Serial.println(inputString);
inputString.toCharArray(buff, inputString.length());
fprintf(testFile,buff);
// digitalWrite(6, LOW);
// close the file
fclose(testFile);
}
else
{
// if the file didn't open, print an error
Serial.println("error opening test.txt");
}
}
}
}
/*
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') {
digitalWrite(6, HIGH);
stringComplete = true;
}
}
}
#include <SoftwareSerial.h>
SoftwareSerial SIM900(7, 8);
String outMessage1 = "Hello Arduino";
String outMessage2 = "Arduino2";
volatile int NbTopsFan; //measuring the rising edges of the signal
int Calc;
int hallsensor = 2; //The pin location of the sensor
int condition_1 = LOW;
int condition_2 = LOW;
int gsm_condition_1 = HIGH;
int gsm_condition_2 = HIGH;
String destinationNumber = "+6014681xxxx";
void rpm () //This is the function that the interupt calls
{
NbTopsFan++; //This function measures the rising and falling edge of the hall effect sensors signal
}
// The setup() method runs once, when the sketch starts
void setup() //
{
Serial.begin(9600); //This is the setup function where the serial port is initialised,
SIM900.begin(19200);
SIM900power();
delay(20000);
pinMode(hallsensor, INPUT); //initializes digital pin 2 as an input
pinMode(13, OUTPUT);
attachInterrupt(0, rpm, RISING); //and the interrupt is attached
}
// the loop() method runs over and over again,
// as long as the Arduino has power
void SIM900power()
{
digitalWrite(9,HIGH);
delay(1000);
digitalWrite(9,LOW);
delay(5000);
}
void sendSMS1()
{
gsm_condition_2 = HIGH;
SIM900.print("AT+CMGF=1\r"); //AT command to send SMS message
delay(100);
SIM900.println("AT + CMGS = \"" + destinationNumber +"\""); //recipient's mobile number, in international format
delay(100);
SIM900.println(outMessage1); //message to send
delay(100);
SIM900.println((char)26); //End AT command with a^Z, ASCII code 26 or ctrl+z
delay(100);
}
void sendSMS2()
{
gsm_condition_1 = HIGH;
SIM900.print("AT+CMGF=1\r"); //AT command to send SMS message
delay(100);
SIM900.println("AT + CMGS = \"" + destinationNumber +"\""); //recipient's mobile number, in international format
delay(100);
SIM900.println(outMessage2); //message to send
delay(100);
SIM900.println((char)26); //End AT command with a^Z, ASCII code 26 or ctrl+z
delay(100);
}
void gsm_check()
{
if (condition_1 == HIGH && gsm_condition_1 == HIGH) {
condition_1 = LOW;
gsm_condition_1 = LOW;
sendSMS1();
}
else if ( condition_2 == HIGH && gsm_condition_2 == HIGH) {
condition_2 = LOW;
gsm_condition_2 = LOW;
sendSMS2();
}
}
void water_rate()
{
NbTopsFan = 0; //Set NbTops to 0 ready for calculations
sei(); //Enables interrupts
delay (1000); //Wait 1 second
cli(); //Disable interrupts
Calc = (NbTopsFan * 60 / 7.5); //(Pulse frequency x 60) / 7.5Q, = flow rate in L/hour
Serial.print (Calc, DEC); //Prints the number calculated above
Serial.print (" L/hour\r\n"); //Prints "L/hour" and returns a new line
}
void loop ()
{
water_rate();
if ( Calc > 100 ) {
digitalWrite(13, HIGH);
condition_1 = HIGH;
}
else {
digitalWrite(13, LOW);
condition_2 = HIGH;
}
gsm_check();
}
I cannot use water flow rate sensor and GSM(SIM900) together. Once I use both then GSM will not work at all. I have tried a lot of methods to solve it but still not succeeded. Hope you guys can give me some help.
I was having the same problem. The solution is to stop the time 2 interrupt from running to send the message.
The edit of your code:
void sendSMS2()
{
cli();
gsm_condition_1 = HIGH;
SIM900.print("AT+CMGF=1\r"); //AT command to send SMS message
delay(100);
SIM900.println("AT + CMGS = \"" + destinationNumber +"\"");
delay(100);
SIM900.println(outMessage2); //message to send
delay(100);
SIM900.println((char)26); //End AT command with a^Z, ASCII code 26 or ctrl+z
delay(100);
sei();
}
The problem is that the sensor can only read using the interrupt, but your sim900 will not function when the interrupt is active. So you'll have to temporarily disable the interrupt and then carry on. Also, SIM900.print("AT+CMGF=1\r"); should be in void loop.
The last problem is that your sim 900 will not send integer. So you'll have to send it as a string. Please follow this example for that: http://microembarcado.blogspot.com.au/p/wr-bridge-send-sms-with-temperature.html
I sat for about 4 hours to figure it out.
Hope this makes things a little simplier for you.