Calling Fields from arrays - c++

I have been working on programming some motors for an Arduino project and wondered if anyone could help me with this.
I am effectively trying to specify HIGH/LOW attributes to things in the array.
Here is what I am wanting to implement into the array.
digitalWrite(in1, HIGH); // Motor 2
digitalWrite(in2, LOW);
digitalWrite(in3, HIGH); // Motor 2
digitalWrite(in4, LOW);
digitalWrite(in5, HIGH); // Motor 3
digitalWrite(in6, LOW);
digitalWrite(in7, HIGH); // Motor 4
digitalWrite(in8, LOW);
I have managed to get the array to work by using the LOW tag, however this tells the motors to not spin at all.
I would like to be able to set them to these values.
In my code, the array I am wanting to edit uses the motors, mtrPin and motorPin attributes.
You can see it for reference here.
// Array of PWM's
int pwmPin = 0;
uint8_t pwms[] = {3,5,6,11};
byte numberPwms = 4;
// Array for motors channels
int mtrPin = 0;
uint8_t motors[] = {4,2,8,7,12,13,9,10};
byte motorPin = 8;
void setup()
{
for (pwmPin = 0; pwmPin < numberPwms; pwmPin++){
for (mtrPin = 0; mtrPin < motorPin; mtrPin++){
pinMode(motors[mtrPin], OUTPUT);
pinMode(pwms[pwmPin], OUTPUT);
};
};
}
void motorLoop(){
// setting the direction to turn and speed
// digitalWrite(in1, HIGH); // Motor 2
// digitalWrite(in2, LOW);
// digitalWrite(in3, HIGH); // Motor 2
// digitalWrite(in4, LOW);
// digitalWrite(in5, HIGH); // Motor 3
// digitalWrite(in6, LOW);
// digitalWrite(in7, HIGH); // Motor 4
// digitalWrite(in8, LOW);
// Set the speed for the Motors
for(int pwmPin = 0; pwmPin < numberPwms; pwmPin++){
for (mtrPin = 0; mtrPin < motorPin; mtrPin++){
pinMode(motors[mtrPin], LOW);
analogWrite(pwms[pwmPin], 200);
};
};
};
void loop()
{
motorLoop();
delay(500);
}

If you have 4 motors with 2 pins each, an array of 8 elements is wrong.
Learn about struct or immediately go to c++ class
struct MotorPins {
const byte DIR;
const byte ON;
const byte PWM; } motors[] = {
//DIR ON PWM
{4, 2, 3 },
{8, 7, 5 },
{12, 13, 6 },
{9, 10, 11}
};
const byte mCount = sizeof(motors)/sizeof(motors[0]); // use in a classic for-loop
void setup (){
for (MotorPins mp: motors) {
pinMode(mp.DIR, OUTPUT);
pinMode(mp.ON , OUTPUT);
}
}
...

Related

How to make an event logger loop work with other loop for arduino uno?

I'm fairly new to this but I've been researching for a while now and no conclusive answer.
How do I make a loop that constantly outputs Serial.println of changes in digitalWrite.
Background info; I am making a traffic light with buttons and pedestrian lights too. I have a sequence for when one of the buttons is pressed but I need a separate loop that outputs changes in lights- which lights are on or which button is pressed. Essentially an event logger that loops throughout the entire script constantly.
**
Sorry, I should have specified; when the button is clicked it goes through a whole sequence, its blocking code. More specifically it's blocking the loop i have for the event logger. How do I work them side-by-side? Whatever I try, it's either the light sequence works or the event logger works but never together. My research indicated that I should use the millis function but I don't know how to implement it.
const int red = 8;
const int yellow = 2;
const int green = 3;
const int p_red = 5;
const int p_green = 6;
const int button1 = 4;
const int button2 = 7;
const int state1 = digitalRead(button1);
const int state2 = digitalRead(button2);
unsigned long waitTime = 500;
void setup() {
pinMode(8, OUTPUT);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, INPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, INPUT);
Serial.begin(9600);
}
void loop() {
// turn on the default lights (traffic green and pedestrian red)
digitalWrite(green, HIGH);
digitalWrite(p_red, HIGH);
if(millis() >= waitTime) {
Serial.print("state: ");
Serial.println(state1);
//delay(1000);
}
if(state1 || state2 == HIGH) {
// State 1 // ID Sequence: 3, 5, 6, 1, 5, 2, 10,
digitalWrite(green, HIGH);
digitalWrite(p_red, HIGH);
delay(3000);
digitalWrite(green, LOW);
// State 2
digitalWrite(yellow, HIGH);
delay(5000);
digitalWrite(yellow, LOW);
// State 3
digitalWrite(red, HIGH);
delay(6000);
digitalWrite(p_red, LOW);
// State 4
digitalWrite(p_green, HIGH);
delay(1000);
digitalWrite(p_green, LOW);
// State 5 - Flashing red v 5 cycles (200ms)
for (int x=0+1; x<5; x++) {
digitalWrite(p_red, HIGH);
delay(200);
digitalWrite(p_red, LOW);
delay(200);
} // State 6
digitalWrite(red, HIGH);
digitalWrite(p_red, HIGH);
delay(2000);
// State 7
digitalWrite(red, LOW);
digitalWrite(green, HIGH);
digitalWrite(p_red, HIGH);
delay(10000);
// State 8
digitalWrite(green, HIGH);
digitalWrite(p_red, HIGH);
delay(8000);
}
}
the problem with this current code is the if statement for the lights not working

How to display "accident alert" on LCD display after timer times out

I'm making a simple program that that runs traffic lights in a loop and has an ultrasonic sensor and a 16x2 LCD. The concept is that if the ultrasonic reads a distance value equal to or below a preset value it is detecting obstruction in an intersection and it starts a timer. When that timer expires, the LCD display's an alert. But if the distance value goes above the preset value while the timer is active it stops. For the traffic light loop I'm using the standard Arduino "delay" function e.g. delay(3000);. The issue I'm having is the once the timer finishes the LCD does not display anything. For the alert timer in the program I'm using a library called millisDelay. This library allows the timer to run without stopping the program.
I have tried using the millisDelay library to run the traffic lights instead of the standard delay function. But that does not work as it puts the traffic lights in a constant loop.
Libraries used:
millisDelay.h and liquidCrystal.h
#include <millisDelay.h>
#include <LiquidCrystal.h>
int red = 22;
int yellow = 23;
int green = 24;
int red2 = 25;
int yellow2 = 26;
int green2 = 27;
const int pingPin = 7; // Trigger Pin of Ultrasonic Sensor
const int echoPin = 6; // Echo Pin of Ultrasonic Sensor
long duration, inches, cm;
millisDelay alertdelay;
millisDelay ledDelay;
const int rs = 36, en = 38, d4 = 40, d5 = 42, d6 = 44, d7 = 46;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup() {
// put your setup code here, to run once:
pinMode(red, OUTPUT);
pinMode(yellow, OUTPUT);
pinMode(green, OUTPUT);
pinMode(red2, OUTPUT);
pinMode(yellow2, OUTPUT);
pinMode(green2, OUTPUT);
pinMode(pingPin, OUTPUT);
pinMode(echoPin, INPUT);
Serial.begin(9600); // Starting Serial Terminal
}
void loop() {
lcd.clear();
lcd.begin(16,2);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(10);
digitalWrite(pingPin, LOW);
duration = pulseIn(echoPin, HIGH);
cm = microsecondsToCentimeters(duration);
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
delay(100);
if (cm>=11){
lcd.setCursor(0,0);
lcd.print("Intersection");
lcd.setCursor(0, 1);
lcd.print("Clear");
}
else if (cm<7){
lcd.setCursor(0,0);
lcd.print("Intersection");
lcd.setCursor(0, 1);
lcd.print("Clear");
alertdelay.start(7000);
Serial.println("delay started");
}
if (alertdelay.isFinished()) {
Serial.println("There is a crash up ahead");
lcd.setCursor(0,0);
lcd.print("Crash Up Ahead");
lcd.setCursor(0,1);
lcd.print("Use Caution");
}
delay(1000);
//'2'refers to intersection number 2
//green off,red2 on, yellow on for 3 seconds
digitalWrite(red2, HIGH);
digitalWrite(green, LOW);
digitalWrite(yellow, HIGH);
delay(3000);
// turn off yellow1, then turn red on for 3 seconds
digitalWrite(yellow, LOW);
digitalWrite(red, HIGH);
delay(3000);
//after 3 seconds keep red 1 on and turn red2 off and green2 on,
//green2 stays on for 15 seconds to let traffic through
digitalWrite(red2, LOW);
digitalWrite(green2, HIGH);
delay(15000);
//after 15 seconds green2 turns off, yellow 2 turns on
//yellow2 turns on for 3 seconds,
digitalWrite(green2, LOW);
digitalWrite(yellow2, HIGH);
delay(3000);
//after 3 seconds, yellow2 turns off, and red 2 turns on
digitalWrite(yellow2, LOW);
digitalWrite(red2, HIGH);
delay(3000);
//3 seconds after red2 turns on, red 1 turns off and
//green 1 turns on for 3 seconds
//red2 stays on
digitalWrite(red, LOW);
digitalWrite(green, HIGH);
delay(14000);
}
long microsecondsToCentimeters(long microseconds) {
return microseconds / 29 / 2;
}
These are the issues with what you are doing.
1) The code that you have written takes 42 seconds to iterate through the loop. So you check if the alertDelay has finished once ever 42 seconds.
2) The second time around the code reaches the back to the start of the loop, you first end up setting the alertDelay again before checking if it is running or is finished, which resets it, as such, your code never reaches the part where it displays the crash.
This is how I would have done things
#include <LiquidCrystal.h>
int red = 22;
int yellow = 23;
int green = 24;
int red2 = 25;
int yellow2 = 26;
int green2 = 27;
const int pingPin = 7; // Trigger Pin of Ultrasonic Sensor
const int echoPin = 6; // Echo Pin of Ultrasonic Sensor
long duration, inches, cm;
long alertDisplayTime = millis(), nextLedSwitchTime = millis();
bool displayAlert = false;
int switch_number=-1;
const int rs = 36, en = 38, d4 = 40, d5 = 42, d6 = 44, d7 = 46;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup() {
// put your setup code here, to run once:
pinMode(red, OUTPUT);
pinMode(yellow, OUTPUT);
pinMode(green, OUTPUT);
pinMode(red2, OUTPUT);
pinMode(yellow2, OUTPUT);
pinMode(green2, OUTPUT);
pinMode(pingPin, OUTPUT);
pinMode(echoPin, INPUT);
lcd.begin(16,2);
Serial.begin(9600); // Starting Serial Terminal
nextLedSwitchTime=1000+millis();
}
void loop() {
lcd.clear();
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(10);
digitalWrite(pingPin, LOW);
duration = pulseIn(echoPin, HIGH);
cm = microsecondsToCentimeters(duration);
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
delay(100);
if (cm>=11){
lcd.setCursor(0,0);
lcd.print("Intersection");
lcd.setCursor(0, 1);
lcd.print("Clear");
displayAlert=false;
}
else if ((cm<7)&&(!displayAlert)){
lcd.setCursor(0,0);
lcd.print("Intersection");
lcd.setCursor(0, 1);
lcd.print("Clear");
alertDisplayTime = millis()+7000;
displayAlert=true;
Serial.println("delay started");
}
if ((displayAlert==true)&&(alertDisplayTime<millis())) {
Serial.println("There is a crash up ahead");
lcd.setCursor(0,0);
lcd.print("Crash Up Ahead");
lcd.setCursor(0,1);
lcd.print("Use Caution");
displayAlert=false;
}
if(nextLedSwitchTime>=millis()){
return;
}
long delay_time=0;
switch_number++;
switch(switch_number){
case 0:
//'2'refers to intersection number 2
//green off,red2 on, yellow on for 3 seconds
digitalWrite(red2, HIGH);
digitalWrite(green, LOW);
digitalWrite(yellow, HIGH);
delay_time=3000;
break;
case 1:
// turn off yellow1, then turn red on for 3 seconds
digitalWrite(yellow, LOW);
digitalWrite(red, HIGH);
delay_time=3000;
//after 3 seconds keep red 1 on and turn red2 off and green2 on,
break;
case 2:
//green2 stays on for 15 seconds to let traffic through
digitalWrite(red2, LOW);
digitalWrite(green2, HIGH);
//after 15 seconds green2 turns off, yellow 2 turns on
delay_time=15000;
break;
case 3:
//yellow2 turns on for 3 seconds,
digitalWrite(green2, LOW);
digitalWrite(yellow2, HIGH);
//after 3 seconds, yellow2 turns off, and red 2 turns on
delay_time=3000;
break;
case 4:
digitalWrite(yellow2, LOW);
digitalWrite(red2, HIGH);
//3 seconds after red2 turns on, red 1 turns off and
delay_time=3000;
break;
case 5:
//green 1 turns on for 3 seconds
//red2 stays on
digitalWrite(red, LOW);
digitalWrite(green, HIGH);
delay_time = 14000;
switch_number=-1;
}
nextLedSwitchTime = millis()+delay_time;
}
long microsecondsToCentimeters(long microseconds) {
return microseconds / 29 / 2;
}
What this code does is it never blocks the loop funciton, so your pusle in function is carried out almost every second along with the check for the crash.
Also, i have set a bit, which tells the code that the alert delay has already started, which ensures that your code does not reset it.

Arduino Sonar and Stepper Motor

I am trying to create an Arduino powered sonar / radar. I currently have a sonar sensor attached to a motor and working on the code. The issue is with the for loop below. The sensor will ping and the motor will then move, repeating the correct number of times. However the values that the sonar sensor returns are either 0 or 1 no matter what the distance is. Any help on identifying the issue would be very appreciated.
/*
Nathan Verdonk
3/15/2019
*/
#include <NewPing.h>
#include <Stepper.h>
const int stepsPerRevolution = 2048; // Steps per revolution
const int rotSpeed = 10; // Speed of rotation in RPM
const int triggerPin = 7; // Trigger pin on sonar sensor
const int echoPin = 6; // Echo pin on sonar sensor
const int maxDistance = 300; // Max distance expected from sensor in cm; do not exceed 400
int val;
Stepper stepper1(stepsPerRevolution, 8, 10, 9, 11); // initialize the stepper library on pins 8 through 11:
NewPing sonar1(triggerPin, echoPin, maxDistance); // initialize the new ping library with predefined values
void setup() {
stepper1.setSpeed(rotSpeed);
Serial.begin(115200);
}
void loop() {
for(int i = 0; i < 50; i++){
delay(50);
val = sonar1.ping_cm();
Serial.println(val);
stepper1.step(1);
}
delay(3000);
}
Problem is not with the code.
As it turns out, the sensor is picky about needing nearly exactly 5 V to run. With the servo and sensor using the same power source, the voltage would drop below 5 V when the servo was running.
Thank you to all who helped.
if you want to trap the distance you could do this process to validate your sensor has no problem (i suppose wiring is right):
// defines pins numbers
const int triggerPin = 7;
const int echoPin = 6;
// defines variables
long duration;
int distance;
void setup() {
pinMode(triggerPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
Serial.begin(115200); // Starts the serial communication
}
void loop() {
delay(50);
// Clears the triggerPin
digitalWrite(triggerPin, LOW);
delayMicroseconds(2);
// Sets the triggerPin on HIGH state for 10 micro seconds
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
distance= duration*0.034/2;
// Prints the distance on the Serial Monitor
Serial.print("Distance: ");
Serial.println(distance);
}
In order to generate the ultrasound you need to set the Trig on a High State for 10 µs. That will send out an 8 cycle sonic burst which will travel at the speed sound and it will be received in the Echo pin. The Echo pin will output the time in microseconds the sound wave traveled.
the speed of the sound is 340 m/s or 0.034 cm/µs so you divide by 2 to trap the distance

Multiple if statements and

Thanks in advance for your help.
So I'm working on a pressure sensor. The idea is that when the pressure sensor gets to a certain value, say 10 AND then decreases sharply after it has gotten to 10, activate the buzzer. (So it's like, I pump my car tire to 10 and I want to know if there is a leak)
I just for the life of me can not make this happen. I know I'm just missing something very small but I will greatly appreciate any help.
Below is my code:
#include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
// These constants won't change: const int analogPin = A0; // pin that the sensor is attached to const int ledPin = 13; // pin that the LED is attached to const int threshold = 5; // an arbitrary threshold level that's in the range of the analog input const int buzzer = 9; // pin that the buzzer is connected to.
void setup() { // initialize the LED pin as an output: pinMode(ledPin, OUTPUT); // initilizes the pin as an output. pinMode(buzzer, OUTPUT); // Set buzzer - pin 9 as an output
// initialize serial communications: Serial.begin(9600); lcd.begin(16, 2); lcd.print ("Pressure in kpa"); }
void loop() { // read the value of the pressure sensor: float sensorValue = analogRead(analogPin); // int kpa = (((sensorValue*5)/1024)*(120/5)-116); // 116 was subtracted to equilibrate the sensor int kpa = ((sensorValue * 5 / 1024) * (15 / 5) * (6.894 / 1) - 10); // // if the analog value is greater than whatever threshold we use , turn on the LED:
if (kpa > threshold )
{
digitalWrite(ledPin, HIGH);
digitalWrite(buzzer, HIGH);
tone(buzzer, 1000); // this controls the picth of the sound. (Hz)
delay(1000); } else {
digitalWrite(ledPin, LOW);
digitalWrite(buzzer, LOW);
noTone(buzzer); // Stop sound...
delay(1000); }
// print the analog value: Serial.println(kpa); delay(1); // delay in between reads for stability lcd.setCursor (0, 1); lcd.print (kpa);
}
Thanks.
I have edited the code to reflect what you are trying to do.
Essentially you need to check if your pressure is increasing or decreasing.
So for this you can take two readings and compare them; one reading is taken before the other. If the latest reading is higher than the previous then its going up, no cause for alarm.
If the latest reading is less that the previous then the pressure is going down. So, cause for alarm but not just yet...
TWO conditions need to be met before the alarm sounds, the pressure needs to be on a downward path AND the pressure needs to be below the threshold value.
kpa must be going down AND be below threshold:
(val < previous && val < threshold)
See if this works, sorry I rushed it a bit and haven't tested it at all:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
// These constants won't change:
const int analogPin = A0; // pin that the sensor is attached to
const int ledPin = 13; // pin that the LED is attached to
const int threshold = 5; // an arbitrary threshold level that's in the range of the analog input
const int buzzer = 9; // pin that the buzzer is connected to.
int val = 0; // store value
int previous; // previous reading
void setup()
{
pinMode(ledPin, OUTPUT); // initialize the LED pin as an output:
pinMode(buzzer, OUTPUT); // Set buzzer - pin 9 as an output
Serial.begin(9600); // initialize serial communications:
lcd.begin(16, 2);
lcd.print ("Pressure in kpa");
}
void loop() {
float sensorValue = analogRead(analogPin); // read the value of the pressure sensor:
int kpa = ((sensorValue * 5 / 1024) * (15 / 5) * (6.894 / 1) - 10);
// we want to check if this is going up or down.
previous = val;
val = kpa;
if (val > previous) {
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, HIGH); // make LED flashy-flashy if its going up
delay(1000);
}
else if (val < previous && val < threshold) {
digitalWrite(ledPin, LOW); // ... and we switch off the LED
tone(buzzer, 1000); // WEE WAH WEE WAH WEE WAH
delay(1000);
}
}
I added a flashing LED to the code because flashing LEDs are just better.
I also used an else...if statement.
Hopefully this will work.
Cheers,
Ingwe.

Distance controlled led

I'm trying to create a distance controlled LED that turns off at a certain distance. I'm using an arduino Leonardo and a distance sensor. At the moment when I plug in my board the led stays on permanently and doesn't turn off when the distance reduces. Please can you tell me what needs changing in order for this to work?
const int TrigPin = 2;
const int EchoPin = 3;
float cm;
int ledPin = 12; //define ledPin12 is the output port of led’s level.
int val = 0; //define original of val.
void setup()
{
Serial.begin(9600);
pinMode(TrigPin, OUTPUT);
pinMode(EchoPin, INPUT);
pinMode(ledPin, OUTPUT); //set ledPin output
}
void loop()
{
digitalWrite(TrigPin, LOW); //Low-high-low level sent a short time pulse to TrigPin
delayMicroseconds(2);
digitalWrite(TrigPin, HIGH);
delayMicroseconds(10);
digitalWrite(TrigPin, LOW);
cm = pulseIn(EchoPin, HIGH) / 58.0; //Echo time converted into cm
cm = (int(cm * 100.0)) / 100.0; // retain two decimal places
Serial.print(cm);
Serial.print("cm");
Serial.println();
delay(1000);
val = analogRead(EchoPin); //get the value from sensor
if(val<=1)
{
//512=2.5V, if want the sensor be more sensitive, increase the number, or lese low the number.
digitalWrite(ledPin, HIGH); //when the value of val is less than 512(2.5V), light up led lamp
}
else
{
digitalWrite(ledPin, LOW);
}
}
I am guessing the sensor is similar to an SRF005. You should include that detail in your question.
The trigger looks okay, but there is no harm in pulsing a little longer, say 20 us, to make sure. The capturing of the echo looks right, except that that datasheet I found says to divide by 5.8, not 58.0, and the return value is an unsigned long, not float..
But you shouldn't be using analogRead() on the echo pin. It will be 0 at that point. Rather, you already have the distance in the cm variable.
(There are sensors which use pin voltage to indicate distance as well, but they don't have trigger and echo pins. Which kind are you actually using?)
void loop()
{
int cm = 0;
digitalWrite(TrigPin, LOW); //Low-high-low level sent a short time pulse to TrigPin
delayMicroseconds(2);
digitalWrite(TrigPin, HIGH);
delayMicroseconds(10); // <<<<<<<<<<<<<<<<<<<<<<<< Change to 20
digitalWrite(TrigPin, LOW);
cm = (int)(pulseIn(EchoPin, HIGH) * 10 / 58); //Echo time converted into cm <<<<<<<<< 5.8 ????
Serial.print(cm);
Serial.print("cm");
Serial.println();
if(cm < 50)
{
digitalWrite(ledPin, HIGH);
}
else
{
digitalWrite(ledPin, LOW);
}
delay(1000);
}