I am using HC-05 with arduino and controlling a motor.
I want a motor to run till a specific value (k) every time I send a character (Eg. 'R') from my app to Bluetooth. I am able to it once, but when I send 'R' again, It doesnot work.
I want that the motor should run whenever I send the character 'R'.
Arduino code
#define stpwm 13
#define stdir 12
int j=0;
int k=20;
char inChar;
void setup() {
Serial.begin(9600);
pinMode(stpwm, OUTPUT);
pinMode(stdir, OUTPUT);
}
void loop() {
if (Serial.available() > 0 ) { // Checks whether data is comming from the serial port
inChar = (Serial.read()); // Reads the data from the serial port
}
if (inChar == 'R')
{
if (j<=k)
{
analogWrite(AN2, 100);
analogWrite(AN1, 50);
analogWrite(stpwm, 50);
digitalWrite(stdir, HIGH);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
delay(100);
Serial.println(j);
j++;
}
analogWrite(stpwm,0);
}
Try
if (inChar == 'R')
{
while (j<=k)
{
analogWrite(AN2, 100);
analogWrite(AN1, 50);
analogWrite(stpwm, 50);
digitalWrite(stdir, HIGH);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
delay(100);
Serial.println(j);
j++;
}
j=0;
analogWrite(stpwm,0);
}
There is one main issue with your code:
the variable you use to control the if statement never resets, so it comes a time (when j >= k) that it can never be true unless you restart the system;
Although Pradeep's answer has potential to work, it would lock your system in a loop, while j is less then k.
Therefore, if you want to implement future control code in your system, this could become an issue. For instance, if you need to have an emergency stop set as another letter, this would only be read if you're not stuck within the while loop.
I'd recommend making use of a very simple structure: else; as per below:
#define stpwm 13
#define stdir 12
#define k 20
uint8_t j=0;
char inChar[1];
void setup() {
Serial.begin(9600);
pinMode(stpwm, OUTPUT);
pinMode(stdir, OUTPUT);
}
void loop() {
if (Serial.available() > 0 ) { // Checks whether data is comming from the serial port
inChar = (Serial.read()); // Reads the data from the serial port
}
if (inChar == 'R')
{
if (j<=k)
{
analogWrite(AN2, 100);
analogWrite(AN1, 50);
analogWrite(stpwm, 50);
digitalWrite(stdir, HIGH);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
delay(100);
Serial.println(j);
j++;
}
}
else{
// resets both j and inChar, so that the iteration does not restart
j = 0;
inChar = "";
// turn off signal only when this criteria is met: j > k
analogWrite(stpwm, 0);
}
}
I also made some minor changes to your code:
Defined k as a constant, as you won't be changing it on your program
declared j as an 8-bit integer, which holds values that range from 0 to 255; this saves memory
modified the position where you were turning off stpwm. The way it was set, your signal always turned off at the end of each iteration, which could damage your motor (you were, in a way implementing another pulse modulation)
Hope this helps.
Related
i am trying to make a program that turns on ,off and blinks an led with the help from bluetooth
On and of were pretty easy to replicate,but i can't make the blink to work.There are to options either blinks once,either if i ad a while it never stops from looping.i tried with both if and case.Can somebody help me.I am using an esp32.
The code with if:
#include "BluetoothSerial.h"
#include <Arduino.h>
#include <analogWrite.h>
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
int received;// received value will be stored in this variable
char receivedChar;// received value will be stored as CHAR in this variable
const char turnON ='a';
const char turnOFF ='b';
const char turnBLINK= 'c';
//const char turnFADE='d';
const int LEDpin = 12;
//int brightStep = 1;
//int brightness = 0;
void setup() {
Serial.begin(115200);
SerialBT.begin("Mono"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
Serial.println("To turn ON send: a");//print on serial monitor
Serial.println("To turn OFF send: b"); //print on serial monitor
pinMode(LEDpin, OUTPUT);
// analogWriteResolution(LEDpin, 12);
}
void loop() {
receivedChar =(char)SerialBT.read();
if (Serial.available()) {
SerialBT.write(Serial.read());
}
if (SerialBT.available()) {
// while(SerialBT.available()){
// receivedChar =(char)SerialBT.read();
// }
SerialBT.print("Received:");// write on BT app
SerialBT.println(receivedChar);// write on BT app
Serial.print ("Received:");//print on serial monitor
Serial.println(receivedChar);//print on serial monitor
//SerialBT.println(receivedChar);//print on the app
//SerialBT.write(receivedChar); //print on serial monitor
if(receivedChar == turnON)
{
SerialBT.println("LED ON:");// write on BT app
Serial.println("LED ON:");//write on serial monitor
digitalWrite(LEDpin, HIGH);// turn the LED ON
}
if(receivedChar == turnOFF)
{
SerialBT.println("LED OFF:");// write on BT app
Serial.println("LED OFF:");//write on serial monitor
digitalWrite(LEDpin, LOW);// turn the LED off
}
if(receivedChar == turnBLINK)
{
SerialBT.println("LED blink:");// write on BT app
Serial.println("LED blink:");//write on serial monitor
while (receivedChar == turnBLINK){
//receivedChar =(char)SerialBT.read();
//if(receivedChar != turnBLINK){
// break;
// } else {
digitalWrite(LEDpin, HIGH);// turn the LED off
delay(1000);
digitalWrite(LEDpin,LOW);
delay(1000);
if(receivedChar != turnBLINK){
break; }
}
}
}
delay(20);
}
and with case:
#include "BluetoothSerial.h"
#include <Arduino.h>
#include <analogWrite.h>
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
int received;// received value will be stored in this variable
char receivedChar;// received value will be stored as CHAR in this variable
char data;
int option;
int blink=0;
const int LEDpin = 12;
void setup() {
Serial.begin(115200);
SerialBT.begin("Mono"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
Serial.println("To turn ON send: 1");//print on serial monitor
Serial.println("To turn OFF send: 0"); //print on serial monitor
pinMode(12, OUTPUT);
}
void loop(){
receivedChar =(char)SerialBT.read();
// if (Serial.available()) {
// SerialBT.write(Serial.read());
// }
if (SerialBT.available()) {
// while(SerialBT.available()){
// receivedChar =(char)SerialBT.read();
// }
SerialBT.print("Received:");// write on BT app
SerialBT.println(receivedChar);// write on BT app
Serial.print ("Received:");//print on serial monitor
Serial.println(receivedChar);//print on serial monitor
//SerialBT.println(receivedChar);//print on the app
//SerialBT.write(receivedChar); //print on serial monitor
data=receivedChar;
if(data == '0')
{
option = 0;
blink=0;
}else if(data == '1')
{
option = 1;
blink=0;
}else if(data == '2')
{
option = 2;
blink=1;
}
switch (option)
{
case 0: // LED OFF
digitalWrite(LEDpin, LOW);
break;
case 1: //LED ON
digitalWrite(LEDpin, HIGH);
break;
case 2:
while(blink=1){// LED BLINK
digitalWrite(LEDpin , HIGH);
delay(200);
digitalWrite(LEDpin, LOW);
delay(200);
}
break;
}
}
}
First of all, you should clean your code to a minimum reproducible example. Remove all unnecessary comments and pieces of code that do not represent the main problem you are facing.
After a quick skim over your code, I immediately noticed this:
while(blink=1){// LED BLINK
digitalWrite(LEDpin , HIGH);
delay(200);
digitalWrite(LEDpin, LOW);
delay(200);
}
where it should be while(blink==1){ } --> very common mistake. This should be a comparison, NOT an assignment.
Now, you mention that it never stops running. Even after correcting the error I just pointed at, what part inside of your while loop breaks the logic of blink from being equal to 1? Otherwise, the while-loop will never stop
Finally, do not read the serial data inside the main loop(). Use SerialEvent, rather.
Again, it is quite tricky to follow the flow of your code. I suggest you divide your code into functions in order to make it more readable.
I have verified that its not a wiring problem by using some non library example code, so it seems the problem is not with the circuit.
I'm expecting the following code to run the motor in one direction 200 steps then run 200 steps in the opposite direction. It seems to run the initial 200 steps but then stops, why?
In the setup function:
stepper.setCurrentPosition(0);
// Set the maximum speed in steps per second:
stepper.setMaxSpeed(1000);
In the loop function:
while(stepper.currentPosition() < 300){
stepper.moveTo(200);
stepper.setSpeed(200);
stepper.run();
if (stepper.distanceToGo() == 0) {
stepper.moveTo(-stepper.currentPosition());
stepper.setSpeed(200);
stepper.run();
}
}
Here's my entire code. The if/else at the bottom is where I want to run the motor. I've put in some non working example code in this block as an example:
#include <deprecated.h>
#include <MFRC522.h>
#include <MFRC522Extended.h>
#include <require_cpp11.h>
// Include the AccelStepper library:
#include <AccelStepper.h>
// constants won't change. They're used here to set pin numbers:
const int BUTTON_PIN = 2; // the number of the pushbutton pin
#define BLUE 7
#define GREEN 6
#define RED 3
#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 53 // Configurable, see typical pin layout above
#define dirPin 10
#define stepPin 11
#define motorInterfaceType 1
// Variables will change:
String authKeyFob = "123456789";
String card_ID="";
int ledState = 0; // remember current led state
int buttonState = 0;
int oldButtonState = 0;
bool toggle = false;
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
// initialize the pushbutton pin as an pull-up input
// the pull-up input pin will be HIGH when the switch is open and LOW when the switch is closed.
pinMode(BUTTON_PIN, INPUT);
pinMode(GREEN, OUTPUT);
pinMode(RED, OUTPUT);
pinMode(BLUE, OUTPUT);
stepper.setCurrentPosition(0);
stepper.setMaxSpeed(1000);
stepper.setAcceleration(50);
// stepper.setSpeed(200);
// stepper.moveTo(200);
}
void loop() {
/*
// Change direction once the motor reaches target position
if (stepper.distanceToGo() == 0) {
stepper.moveTo(-stepper.currentPosition());
}
// Move the motor one step
stepper.run();
*/
buttonState = digitalRead(BUTTON_PIN);
// read the state of the switch/button:
oldButtonState = LOW; // NEED TO ADD A DECLARATION FOR THIS BEFORE SETUP
buttonState = digitalRead(BUTTON_PIN);
// Look for new cards, and select one if present
if (!mfrc522.PICC_IsNewCardPresent() ) {
}
if(mfrc522.PICC_ReadCardSerial() ){
card_ID="";
for (byte i = 0; i < mfrc522.uid.size; i++) {
card_ID += mfrc522.uid.uidByte[i];
}
if(card_ID == authKeyFob){
toggle = !toggle;
delay(200);
}
}
// if the button just became pressed...
if(buttonState == HIGH && oldButtonState==LOW){
toggle = !toggle; // same thing, toggle our variable.
delay(200);
}
if (toggle) {
digitalWrite(GREEN, HIGH);
digitalWrite(RED, LOW);
stepper.moveTo(200);
stepper.setSpeed(200);
stepper.run();
} else {
digitalWrite(GREEN, LOW);
digitalWrite(RED, HIGH);
stepper.moveTo(200);
stepper.setSpeed(200);
stepper.run();
}
oldButtonState = buttonState; // save the button state for next time
}
The run method doesn't block. It just takes one step if it is time. So let's step through your code. First we enter the while loop and tell it to step to 200 and set the speed and call run. We keep repeating that over and over. If we get to a point where we have 0 to go then you say moveTo the negative position, set the speed, call run once and then the while loop exits and repeats. On that repeat we say move to 200 and start calling run on that. So you're only calling run once with the moveTo set to the negative number.
You need to rethink the logic on this. I don't know what else is in your loop, so it's hard to say what exactly you want. If you really insist on it being blocking in the while loop then:
stepper.moveTo(200);
stepper.setSpeed(200);
while(stepper.distanceToGo() != 0){
stepper.run();
}
stepper.moveTo(-200);
while(stepper.distanceToGo != 0){
stepper.run();
}
This code moves the stepper in each direction.
if (toggle) {
digitalWrite(GREEN, HIGH);
digitalWrite(RED, LOW);
while(stepper.currentPosition() <= 200){
stepper.moveTo(200);
stepper.setSpeed(200);
stepper.runSpeedToPosition();
if(stepper.currentPosition()==200){
break;
}
}
} else {
digitalWrite(GREEN, LOW);
digitalWrite(RED, HIGH);
while(stepper.currentPosition() >= -200){
stepper.moveTo(-200);
stepper.setSpeed(200);
stepper.runSpeedToPosition();
if(stepper.currentPosition()==-200){
break;
}
}
}
I have the script below and it works.
But I want to control it with a word like on or off instead of one character.
I tried and searched a lot but without success.
/*
Simple LED sketch
*/
int led = 13; // Pin 13
void setup()
{
pinMode(led, OUTPUT); // Set pin 13 as digital out
// Start up serial connection
Serial.begin(115200); // baud rate
}
void loop()
{
if (Serial.available()) {
int ser = Serial.read(); //read serial as ascii integer
if (ser == 'a') { //is this serial byte the ASCII equivalent of 0 through 9?
digitalWrite(led, HIGH); // on
Serial.println("aan");
}
else if (ser == 'u') {
digitalWrite(led, LOW); // off
Serial.println("uit");
}
}
}
Use Serial.readStringUntil(terminator) to read a string from the serial.
The sent string needs to be terminated with a newline character.
Chose Newline in the Arduino IDE's Serial Monitor.
String cmd = "";
void loop()
{
if (Serial.available()) {
cmd = Serial.readStringUntil('\n');
if (cmd == "on") {
digitalWrite(led, HIGH); // on
Serial.println("aan");
}
else if (cmd == "off") {
digitalWrite(led, LOW); // off
Serial.println("uit");
}
}
}
Your problem is that you are using a char you need to declare a string so you can compare that string to the input, the guy above gave a ok/very slacky/too complex for you answer (sorry no offense I am just trying to show contrast between a complex and a easy answer not trying to offend you) and partially is because he did not explain what he is doing and because he is doing unnecessary/useless work. There is a function in c++ called Serial.readString(), much easier then the stuff up there. Assuming your level of programming (no offense) from your question here is a quick review on data types:
String = ""
int = integer number {1,2,3,4,5,6,...}
char = '' <- Notice the difference from String = ""
float = floating point number {1.2,4.5,...}
(These are not all of them, there is more like byte and so on but just make sure you know how to use the above first)
/*
Simple LED sketch
*/
int led = 7; // Pin 13
String ser; //Declare the string that is going to store what your are going to
//write in the serial
void setup(){
// Start up serial connection
//It's good convention to start the serial before pinMode or any other thing
//in setup
Serial.begin(9600); //I don't know why you need such an high baud rate in
//your thing, 9600 for what you have to do is more than fine, this is just at
//what speed the serial is read (in a very general explanation)
pinMode(led, OUTPUT); // Set pin 13 as digital out
//make sure you put in here wheter you want to start the led "on" or "off"
//Eg you want it to start on, then digitalWrite(led, HIGH);
}
void loop(){
ser = Serial.readString();
if(Serial.available() == 0) { //You can also use a while loop if you want to
//This is telling the arduino: if there is something in the serial, then do...
if(ser == "on"){
Serial.println("on");
digitalWrite(led, HIGH);
}else if(ser == "off"){
Serial.println("off");
digitalWrite(led, LOW);
}
}
}
Hope it helped!
Also notice how the above code with
if(Serial.available())
This is a quite WEIRD and SHADY statement and might not work. That's because you are not really telling the int value into the function Serial.available
As the arduino guidelines specify:
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
viewable here
I am currently trying to do some communication test between a PC and Arduino Uno using an XBee in AT mode.
My test is to send characters from the computer to the XBee and process through conditional statements.
I don't believe this issue is with configuration of the XBees, for I am able to communicate successfully when I watch the Serial monitors.
Here is the code I am running on the Arduino:
#include <SoftwareSerial.h>
SoftwareSerial xBee = SoftwareSerial(1, 0);
int Led = 9;
void setup()
{
pinMode(Led, OUTPUT);
xBee.begin(9600);
}
void loop()
{
if (xBee.available()> 0)
{
if (xBee.read() == 'r')
{
digitalWrite(Led, HIGH);
xBee.write("Led On");
delay(10);
}
else if (xBee.read() == 'o')
{
digitalWrite(Led, LOW);
xBee.write("Led Off");
delay(10);
}
else
{
xBee.write("NR"); // Testing for not recognized characters
}
delay(10);
}
delay(10);
}
I can turn on the LED when sending the character 'r' from the PC to the XBee. The intended result is received back as well. When I try to send the character 'o' from the PC the LED stays on, and I get the response of "NR".
This same result happens with different characters in the else if statement, sending character 'o' as the first character, changing to just if statements, and changing the initial condition to - while xBee.available().
How can I fix this problem?
You need to store the input value of xBee.read() and then use it in the if condition.
You can try this
#include <SoftwareSerial.h>
SoftwareSerial xBee = SoftwareSerial(1, 0);
int Led = 9;
void setup()
{
pinMode(Led, OUTPUT);
xBee.begin(9600);
}
void loop()
{
char read_value = xBee.read();
if(xBee.available()> 0)
{
if ( read_value == 'r')
{
digitalWrite(Led, HIGH);
xBee.write("Led On");
delay(10);
}
else if ( read_value == 'o')
{
digitalWrite(Led, LOW);
xBee.write("Led Off");
delay(10);
}
else
{
xBee.write("NR"); // Testing for not recognized characters
}
delay(10);
}
delay(10);
}
The problem is that you are taking the input with xBee.read() but not storing it.
Only your first if works ie,
if ( read_value == 'r')
{
digitalWrite(Led, HIGH);
xBee.write("Led On");
delay(10);
}
The control is not even going in the else if hence condition for o is not tested.
Traffic light just stays on red rather than alternating.
Wanted it to stay on for 10s then off for 10s, continuing ad infinitum.
Dont want to use the delay function cos need to do other stuff while the LED continues to alternate.
Thanks
int red = 10; // red traffic light LED on pin 10
int redcounter;
// the setup routine runs once when you press reset:
void setup()
{
// initialize the digital pin as an output.
pinMode(red, OUTPUT);
digitalWrite(red, LOW);
redcounter = 0;
}
// the loop routine runs over and over again forever:
void loop()
{
redcounter = redcounter +1;
if(redcounter==1000)
{
redcounter=0;
if(digitalRead(red)==HIGH)
{
digitalWrite(red, LOW);
}
if(digitalRead(red)==LOW)
{
digitalWrite(red, HIGH);
}
}
You try to read a port which is configured as an OUTPUT. I don't know if this is supposed to work, but it would be more clear if you simply use another port as INPUT and feedback the signal you want to check in that port. I'm not sure however if it makes much sense to check the state of a signal you generate yourself (?). Moreover your redcounter is just "Active waiting", and arduino provides a delay function which does exactly that.
int red=10;
int signal=11;
void setup()
{
pinMode(red, OUTPUT);
pinMode(signal, INPUT);
digitalWrite(red, LOW);
}
void loop()
{
delay(1000);
if(digitalRead(signal)==HIGH)
{
digitalWrite(red, LOW);
}
if(digitalRead(signal)==LOW)
{
digitalWrite(red, HIGH);
}
}
Use elseif instead of if here:
if(digitalRead(red)==HIGH)
{
digitalWrite(red, LOW);
}
else if(digitalRead(red)==LOW)
{
digitalWrite(red, HIGH);
}
In your old solution every time red turned low, it was turned high a moment later.
Two issues in your code are that digitalread will not read an output pin and if you use an increment counter you won't be able to accurately denote time. Sorry if I missed a bracket or something I was doing this on the mobile app.
Use this:
int red = 10; // red traffic light LED on pin 10
int redcounter;
boolean pinState = false;
int delayTime = 10000;
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(red, OUTPUT);
digitalWrite(red, LOW);
redcounter = millis();
}
// the loop routine runs over and over again forever:
void loop() {
if((millis() - red counter) > delayTime) {
redcounter=millis();
if(pinState) {
digitalWrite(red, LOW);
pinState = false;
}
else {
digitalWrite(red, HIGH);
pinState = true;
}
}
}