Arduino digital read is not working as expected - arduino

I have been using my Arduino to control motor polarity with a Cytron MD-10 motor driver shield, and I had it working.
Then when I came back to work it seemed as though the digital read pins were not differentiating between high and low voltage and one of the lights was powered on continuously.
The outputs function as set up with a continuous supply of measured 4.84 volts and then the switch is closed the voltage drops to 0 and the corresponding loop should be entered. Is my board fried?
Anything I should try?
const int outSwitch = 13;
const int inSwitch = 12;
const int pinPWM = 3;
const int pinDir = 2;
int lightOne = 11;
int lightTwo = 10;
static int Dir = 1;
static int cycleCounter = 0;
void setup() {
// Set Pin Out/Inputs:
pinMode(pinPWM, OUTPUT);
pinMode(pinDir, OUTPUT);
pinMode(outSwitch, INPUT);
pinMode(inSwitch, INPUT);
pinMode(lightOne, OUTPUT);
pinMode(lightTwo, OUTPUT);
analogWrite(pinPWM, LOW);
}
void loop() {
// Both read a low input value from the switch and then makes
// direction the opposite causing it to travel backwards:
if(digitalRead(inSwitch == LOW)){
analogWrite(pinPWM, HIGH);
digitalWrite(pinDir, Dir);
digitalWrite(lightOne, LOW);
digitalWrite(lightTwo, HIGH);
}
else if(digitalRead(outSwitch == LOW)){
analogWrite(pinPWM, HIGH);
digitalWrite(pinDir, -Dir);
digitalWrite(lightOne, LOW);
digitalWrite(lightTwo, HIGH);
}
}

Sma correctly identified the problem as a misplacement of the parentheses:
if (digitalRead(inSwitch == LOW)) // OOPS!
This compares inSwitch to LOW, which probably returns false. Since digitalRead expects an int, that false is converted to 0. So you do a read of pin 0. I don't think there is a pin 0, so you probably get an error. That return value is then implicitly compared to 0 in order to determine which branch of the if-statement to take.
The correct statement would look like this:
if (digitalRead(inSwitch) == LOW)
(Community Wiki because I'm just trying to provide a more detailed answer. I'm not trying to get rep for someone else's observation.)

What does analogWrite(pinPWM, HIGH); even mean? Missing a value (0-255), HIGH is not a valid value.

Related

Arduino Automatic Clothes Line : How can I make my meet the different criteria?

So I'm a novice in programming and is helping my friend with coding an automatic clothes line for a project.
Each component works fine individually but when I put all the code together the motors are confused in which direction to go. can anyone take a look at it and give us feedback?
We have a rain sensor, light sensor, 2 switches , and a motor.
When it rains OR when it is dark the motors pulls the clothes in and when the the clothes reaches the end it touches switch 1 and stops the motors.
When it stop rains/sunny AND/OR when there light it pulls the clothes out in the open.
Here is the code I was provided:
**
#include <Stepper.h>
//motors
const int stepsPerRevolution = 400;
//motor speeds
Stepper myStepper = Stepper(stepsPerRevolution, 2,4, 3, 5);//clockwise
Stepper myStepper2 = Stepper(stepsPerRevolution, 5, 3, 4, 2);//counterclockwise
//rain sensor
const int capture_D =4;
const int capture_A = A0;
int val_analogique;
int led = 8;
//switches
const int switch1 = A3;
const int switch2 =A4;
void setup() {
// put your setup code here, to run once:
// motors
myStepper.setSpeed(60);
myStepper2.setSpeed(60);
//rain sensor
pinMode(capture_D, INPUT);
pinMode(capture_A, INPUT);
pinMode(led, OUTPUT);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
//light sensors
unsigned int AnalogValueL;
AnalogValueL = analogRead(A5);
Serial.println(AnalogValueL);
delay(2000);
//rainsensor
if((digitalRead(capture_A) && digitalRead(capture_D)) ==LOW)
{
digitalWrite(led, HIGH);
myStepper2.step(stepsPerRevolution); // bringclothesout
Serial.println("DRY");
delay(1000);
}
else
{
//when it rains the clolthes re brought in
digitalWrite(led, LOW);
Serial.println("WET");
myStepper.step(stepsPerRevolution);//bring clothes in
delay(1000);
}
if(AnalogValueL < 1010)
{
digitalWrite(led, HIGH);
Serial.println("SUNNY");
myStepper2.step(stepsPerRevolution);
delay(1000);
}
else
{
digitalWrite(led, LOW);
Serial.println("Dark");
myStepper.step(stepsPerRevolution);
delay(1000);
}
//switches
unsigned int AnalogValueS;
AnalogValueS = analogRead(switch1);
Serial.println(AnalogValueS);
delay(2000);
if(AnalogValueS <= 1000)
{
digitalWrite(led, HIGH);
Serial.println("Off");
myStepper.setSpeed(0);
}
else
{
digitalWrite(led, LOW);
Serial.println("on");
}
unsigned int AnalogValueSS;
AnalogValueSS = analogRead(switch2);
Serial.println(AnalogValueSS);
delay(2000);
if(AnalogValueSS <= 1000)
{
digitalWrite(led, HIGH);
Serial.println("ON");
}
else
{
digitalWrite(led, LOW);
Serial.println("Off");
}
*/
}//end of program
**
Feedback?
Here's my feedback:
Your code needs a little bit of tidying up for the sake of clarity and readability.
It is always recommended to declare your Serial.begin(); at the beginning of the setup() function.
You forgot to declare the switches pins as inputs:
pinMode(switchX, INPUT); // where X = 1, 2
Why are you using analog pins as switch inputs? (const int switch1 = A3). If you are connecting ON/OFF switches here you should rather use digital pins. In case your switches are the light sensors, then they are fine (read comment 9 below). Otherwise, this:
AnalogValueS = analogRead(switch1);
is wrong as you cannot read a digital switch with an analogRead()
Additionally, you don't say if your switches are active HIGH or active LOW, namely, if they pulse LOW when pressed and HIGH when released or viceversa.
One important mistake is that you are assigning pin 4 twice for different functions. First as a motor pin, then as capture_D:
Stepper myStepper = Stepper(stepsPerRevolution, 2, 4, 3, 5);
Stepper myStepper2 = Stepper(stepsPerRevolution, 5, 3, 4, 2);
const int capture_D = 4;
You read the analog value in a variable declared inside the main() loop while you previously declared int val_analogique without using it. This is poor consistency.
Similarly, you read from analog pin A5 without previously declaring it as an INPUT:
AnalogValueL = analogRead(A5);
The flow of your loop could be affected by that many delay() throughout the code.
You expressed having three sensors:
We have a rain sensor, light sensor, 2 switches, and a motor.
It is good practice to label the pins from these sensors with a representative name from the sensor in question: e.g.:
const int lightSensor1 = 4;
In the C++ mindset is common practice to use enums to define states from a specific event or scenario. For instance:
typedef enum {
RAINING,
DARK,
NOT_RAINING,
SUNNY
}WEATHER_CONDITIONS;
WEATHER_CONDITIONS currentCondition = SUNNY;
where the typedef means that you are creating your own data type WEATHER_CONDITIONS and their assigned values are 0,1, 2,... according to their order.
With regards to the Stepper.h library you are declaring two Stepper instances expecting that in that way you will reverse the direction of the motor. That is NOT how it works. According to the library (Stepper.cpp) to reverse the motor, you need to send a negative value as an argument to reverse its direction. Please read line 184 from this file from the library.
On this line:
if((digitalRead(capture_A) && digitalRead(capture_D)) ==LOW)
you are attempting to read a digital value from an analog pin. While it might work if the voltage on that pin is at a logic level, this is not recommended.
Finally, you SHOULD connect the switches for stopping the motor to INTERRUPT pins. This is a more effective way to detect when the switch has been pressed and take immediate action by changing a state. You would have to use pins 2 and 3 (INT0 and INT1).
This is my take on this code. Compiled correctly but UNTESTED!
#include <Arduino.h>
#include <Stepper.h>
/*Constants*/
//motor speeds
const int stepsPerRevolution = 400;
/*Pinout declarations*/
// Motor pins
const int motorPins[4] = {2, 3, 4, 5};
//rain sensor
const int capture_D = 4; // capture_D
const int capture_A = A0; // A0
const int lightSensor = A5;
//switches
const int switch1 = 9; // Previously: A3 So this is an analog switch?
const int switch2 = 10; // Previously: A4 You should assing this to other two digital pins
//Led
const int led = 8;
/*Custom variables*/
typedef enum {
DARK,
SUNNY
} LIGHT_CONDITIONS;
LIGHT_CONDITIONS lightState = SUNNY;
const char* lightLabels[] = {"DARK",
"SUNNY"};
typedef enum {
DRY,
WET
} HUMIDITY_CONDITIONS;
HUMIDITY_CONDITIONS humidityState = DRY;
const char* humidityLabels[] = {"DRY",
"WET"};
typedef enum {
CW, // Let's assume that this is bring them in
CCW, // this is take them out
STOP
} MOTOR_DIRECTION;
MOTOR_DIRECTION currentDirection = STOP; // This declares a default state
const char* directionLabels[] = {"Clothes In",
"Clothes Out"};
/*General variables*/
int rawLightValue;
// Objects declaration
Stepper myStepper = Stepper(stepsPerRevolution,
motorPins[0],
motorPins[1],
motorPins[2],
motorPins[3]);
void activateMotor(int direction) {
switch (direction) {
case MOTOR_DIRECTION::CW:
myStepper.step(-stepsPerRevolution);
currentDirection = CW;
break;
case MOTOR_DIRECTION::CCW:
myStepper.step(stepsPerRevolution);
currentDirection = CCW;
break;
case MOTOR_DIRECTION::STOP:
currentDirection = STOP;
myStepper.step(0);
break;
default:
// so much empty
break;
}
}
void setup() {
Serial.begin(9600);
// motors
myStepper.setSpeed(60);
//rain sensor
pinMode(capture_D, INPUT);
pinMode(capture_A, INPUT);
pinMode(switch1, INPUT);
pinMode(switch2, INPUT);
pinMode(lightSensor, INPUT);
pinMode(led, OUTPUT);
}
void loop() {
// First, read light sensor
rawLightValue = analogRead(lightSensor);
Serial.println(rawLightValue);
if (rawLightValue < 1010) {
digitalWrite(led, HIGH);
lightState = SUNNY;
Serial.println(lightLabels[lightState]);
} else {
digitalWrite(led, LOW);
lightState = DARK;
Serial.println(lightLabels[lightState]);
}
// Then read rain sensor --> digital portion only, granted that you have calibrated
// its pulsing voltage corectly. I am assuming that you are using one of these sensors:
// https://circuitdigest.com/microcontroller-projects/rain-detector-using-arduino
if (digitalRead(capture_D) == LOW) {
digitalWrite(led, HIGH);
humidityState = DRY;
Serial.println(humidityLabels[humidityState]);
}
else {
//when it rains the clolthes re brought in
digitalWrite(led, LOW);
humidityState = WET;
Serial.println(humidityLabels[humidityState]);
}
// Based on these conditions, activate the motor accordingly
/* When it rains OR when it is dark the motors pulls the clothes in and when
the the clothes reaches the end it touches switch 1 and stops the motors.
*/
if ((humidityState == WET) || (lightState == DARK)) {
// While the switch is released, meaning that the switch has NOT been pressed:
while (digitalRead(switch1) == HIGH) {
activateMotor(CCW);
Serial.println(directionLabels[currentDirection]);
}
// Finally, let the motors go until the swithces tell the system to stop the motor
activateMotor(STOP);
}
if ((humidityState == DRY) && (lightState == SUNNY)) {
// While the switch is released, meaning that the switch has NOT been pressed:
while (digitalRead(switch2) == HIGH) {
activateMotor(CW);
Serial.println(directionLabels[currentDirection]);
}
// Finally, let the motors go until the swithces tell the system to stop the motor
activateMotor(STOP);
}
}

How to prevent an initial HIGH output in PIR Sensor

I am testing out the HC-SR501 PIR sensor on arduino. I tried a simple code tutorial online
int buzz = 13;
int pir = 2;
int value = 0;
int pirState = LOW;
void setup() {
pinMode(buzz, OUTPUT);
pinMode(pir, INPUT);
Serial.begin(9600);
}
void loop() {
delay(5000);
value = digitalRead(pir);
if (value == HIGH) {
digitalWrite(buzz, HIGH);
if (pirState == LOW) {
Serial.println("Motion Detected!");
pirState = HIGH;
}
} else {
digitalWrite(buzz, LOW);
if (pirState == HIGH){
Serial.println("Motion Ended!");
pirState = LOW;
}
}
}
This works, however, I'm trying to initialize it to a LOW output. When I first turn on the board, it initially gives me a high output, and so the buzzer activates instantly, even though I placed it away from myself. The serial prints out Motion Detected. I tried adding a delay, however it still gives out a HIGH output afterwards. Anyone knows how to solve this?
Thank you!
The pinMode sets the pin as an output, but the default state is LOW, so there should be no problem with it.
However, pin 13 is wired to onboard LED. And the onboard LED is also used by bootloader to signal its activity after the reset. You should check other pins but 13.

Why 2nd PIR sensor is always HIGH?

I an getting a constant HIGH from 'inputPintwo' on the serial monitor. When 'inputPin' goes HIGH the relay is triggered and works properly because 'inputPintwo' is also HIGH (all the time).
I have a Very similar setup to: 2 PIR motion sensors +Arduino
I am not using pin 0 or 1 like the above answered question. I have replaced the sensor with a different one, in case it was bad hardware. I also unplugged the sensor and it still reads HIGH. The jumper is on retriggering on both sensors.
int ledPin = 13;
int inputPin = 2;
int inputPintwo = 4;
int pirState = LOW;
int val = 0;
int valtwo = 0;
#define RELAY1 7
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(inputPin, INPUT);
pinMode(inputPintwo, INPUT);
pinMode(RELAY1, OUTPUT);
Serial.begin(9600);
}
void loop(){
val = digitalRead(inputPin);
valtwo = digitalRead(inputPintwo);
if (val == HIGH && valtwo == HIGH) {
digitalWrite(ledPin, HIGH);
if (pirState == LOW) {
Serial.println("Motion detected!");
pirState = HIGH;
Serial.println("Light ON");
digitalWrite(RELAY1,1);
delay(500);
digitalWrite(RELAY1,0);
delay(500);
digitalWrite(RELAY1,1);
delay(500);
digitalWrite(RELAY1,0);
delay(500);
digitalWrite(RELAY1,1);
}
}
else {
digitalWrite(ledPin, LOW);
if (pirState == HIGH){
Serial.println("Motion ended!");
digitalWrite(RELAY1,0);
pirState = LOW;
Serial.println("Light OFF");
}
}
}
I expect both sensors to go HIGH only when motion is detected, which will cause the relay to go on and off several times, then stay on until the timer runs out on the sensors.
To identify the problem I recommend you to start with checking the hardware. You will need voltmeter/multimeter.
Double check if you are interfacing the sensor properly (check datasheet). Didn't you forget to connect e.g. the pull-down resistors?
Check power supply voltage on sensors – is the voltage within
manufacturer specifications?
Check breadboard connections if you are using one.
Check sensor output behaviour (voltage), if there is or is not a movement. Is the voltage constant or not? Constant voltage means that PIR sensor is NOT working properly. Before performing of this test disconnect output from Arduino input.
If everything seems OK or you do not have voltmeter, try to disconnect the PIR sensor and connect a wire between Arduino pin 4 and ground. Does digitalRead(inputPintwo) return LOW? If yes, you know that reading of the pin state works fine.
Below please see some recommendations related to your code:
use #define directive or static const int variable type to define Arduino pins as you do it with relay output pin RELAY1.
Example:
#define LED_PIN 13
#define INPUT_PIN 2
#define INPUT_PINTWO 4
or
static const int ledPin = 13;
static const int inputPin = 2;
static const int inputPintwo = 4;
In your case, where you are only interested in digital value (LOW/HIGH), use built pull-up resistor on the input pins. Thus the log. voltage level on the floating input pin is defined (HIGH). If you do not use pull-up resistors, voltage can be either log. 0 (LOW) or log. 1 (HIGH), what can lead to strange program/state machine behaviour
To activate pull-up resistors in the input pins, use
pinMode(inputPin, INPUT_PULLUP);
pinMode(inputPintwo, INPUT_PULLUP);

Stop getting values from arduino after some time

I have a strange problem, I have Arduino UNO/MEGA and I need to get Gyro sensors's data and I want to see the data in the serial monitor. Seems like a simple task, I wrote a simple C program which collects data from Arduino through serial monitor I can see the data. Everything is working for few minutes and after that, it stops.
This code is supposed to calculate a distance travelled in a line using encoder (PID algorithm implemented using Gyroscope data for straight motion) after reaching desired position, machine takes a U-Turn.
It stop for a second after taking the U-Turn and then starts straight motion again. The problem I'm facing is that the gyroscope readings stop randomly while machine taking the turn. Due to this, the machine keeps rotating about that point without stopping.
#include <Wire.h>
#include <MPU6050.h>
MPU6050 mpu;
float timeStep = 0.01, yaw=0;
const int motor11=6;//LEFT MOTOR FW
const int motor12=7;//LEFT MOTOR BK
const int motor1pwm=3;
const int motor21=8;//RIGHT MOTOR FW
const int motor22=9;//RIGHT MOTOR BK
const int motor2pwm=5;
int flag1 = 0;
int thres1=120;//PWM Values
int thres2=120;
void setup()
{
Serial.begin(115200);
// Initialize MPU6050
while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G))
{
Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
delay(500);
}
mpu.calibrateGyro();
mpu.setThreshold(1);
pinMode(motor11, OUTPUT);
pinMode(motor12, OUTPUT);
pinMode(motor1pwm, OUTPUT);
pinMode(motor21, OUTPUT);
pinMode(motor22, OUTPUT);
pinMode(motor2pwm, OUTPUT);
}
void loop()
{
Vector norm=mpu.readNormalizeGyro();
yaw=yaw+norm.ZAxis*timeStep;
if(flag1 == 0){
straight();
}
if(flag1 == 2){
taketurn();
}
}
void straight()
{
digitalWrite(motor11, HIGH);
digitalWrite(motor12, LOW);
analogWrite(motor1pwm, thres1);
digitalWrite(motor21, HIGH);
digitalWrite(motor22, LOW);
analogWrite(motor2pwm, thres2);
delay(8000);
flag1 = 2;
}
void taketurn()
{
float setPoint = yaw - 500;
digitalWrite(motor11, HIGH);
digitalWrite(motor12, LOW);
analogWrite(motor1pwm, 120);
digitalWrite(motor21, LOW);
digitalWrite(motor22, LOW);
analogWrite(motor2pwm, 120);
while(true)
{
Vector norm = mpu.readNormalizeGyro();
yaw = yaw + norm.ZAxis * timeStep;
Serial.print("Turning Yaw= ");
Serial.println(yaw);
if(setPoint >= yaw) {
digitalWrite(motor11, LOW);
digitalWrite(motor12, LOW);
analogWrite(motor1pwm, thres2);
digitalWrite(motor21, LOW);
digitalWrite(motor22, LOW);
analogWrite(motor2pwm, thres1);
delay(2000);
break;
}
}
flag1 = 0;
}
The serial monitor just stops displaying the reading. This does not happen every time, and it is very random. I want to get proper and continuous data. Is it a logical problem or a board problem?
Normally a random crash would indicate possibly unhandled interrupts or memory overwrite, but looking at your code and it being an Arduino program, it's unlikely to be either. I don't see any divide ops either, so you are not dividing by zero. The two possible things I see is that a) you have a "while (true)" without exit, so surely that could get you into trouble, and b) perhaps your delay functions are called with a very large value unexpectedly, and the MCU is actually just delaying a long time.

Arduino IR Sensors Not Calling Functions

With this code written in the Arduino IDE I used to be able to call functions based on which Infrared sensor detected an object(right, left, or both). I altered the code a little bit lately but I've continued to make sure it wasn't missing any key components which made it work in the first place. I'm not sure if it's an error in my program or hardware but now, no matter what sensor detects an object, my robot just turns slightly to the left.
//Include Servo Library
#include <Servo.h>
//Define Pins for the Sensors and LEDs
#define LsensorPin 8
#define RsensorPin 5
#define LeftTransPin 7
#define RightTransPin 6
I'm using continuous rotation servos so using 0's and 180's is how I would control them at full speed. I checked the numbers over and over but they don't seem to be the problem.
//Constants for driving servo
const int RForward = 0;
const int RBackward = 180;
const int LForward = RBackward;
const int LBackward = RForward;
const int RNeutral = 90;
const int LNeutral = 90; //0 Speed
//Name the Servos for Left and Right Motor
Servo LMotor;
Servo RMotor;
The following 2 functions, when called, transmit an infrared signal through the transmitters. I do not think this is related to the problem because the sensors still detect objects, but my robot just doesn't respond the way I want it to.
//Take Reading from Left IR Sensor
void LeftIRled(){
for(int i=0;i<=384;i++){
digitalWrite(LeftTransPin, HIGH);
delayMicroseconds(13);
digitalWrite(LeftTransPin, LOW);
delayMicroseconds(13);
}
}
//Take Reading from Right IR Sensor
void RightIRled(){
for(int i=0;i<=384;i++){
digitalWrite(RightTransPin, HIGH);
delayMicroseconds(13);
digitalWrite(RightTransPin, LOW);
delayMicroseconds(13);
}
}
These functions control the direction in which the robot moves. I've checked it many times but this could possibly be one of the problems. They basically just control the spin of each individual servo with the previously declared variables.
//Controlling Servo Directions with Functions
void Forward(){
RMotor.write(RForward);
LMotor.write(LForward);
}
void Backup(){
RMotor.write(RBackward);
LMotor.write(LBackward);
}
void Stop(){
RMotor.write(RNeutral);
LMotor.write(LNeutral);
}
void Left(){
RMotor.write(RForward);
LMotor.write(LNeutral);
}
void Right(){
RMotor.write(RNeutral);
LMotor.write(LForward);
}
//Declare INPUT and OUTPUT for each Pin connected
//to Arduino Uno and set them to LOW
void setup(){
pinMode(LeftTransPin, OUTPUT);
digitalWrite(LeftTransPin, LOW);
pinMode(RightTransPin, OUTPUT);
digitalWrite(RightTransPin, LOW);
//drive forward
LMotor.attach(9);
RMotor.attach(10);
Forward();
}
Although I can't pinpoint the problem I believe it has something to do with the loop function. It is here that I transmit the infrared signal, receive it, and then call various functions which control the movement of the robot.
void loop(){
/*Drive forward until you reach an obstacle on either the
right side, left side, or both together(something in front of
you). If the left sensor goes low, he turns right, if the right
sensor goes low, he turns left. if both turn on at the same time
he stops, backs up, and turns right till he is out of danger
*/
int lstate;
int rstate;
LeftIRled();
lstate = digitalRead(LsensorPin);
delay(50);
RightIRled();
rstate = digitalRead(RsensorPin);
delay(50);
if (lstate == LOW && rstate == LOW)
{
Stop();
delay(100);
Backup();
delay(1000);
Stop();
delay(100);
Right();
delay(500);
}
else if (lstate == LOW)
{
Stop();
delay(100);
Backup();
delay(1000);
Right();
delay(500);
}
else if (rstate == LOW)
{
Stop();
delay(100);
Backup();
delay(1000);
Left();
delay(500);
}
else
{
Forward();
}
}
Any help or advice is greatly appreciated!

Resources