I have 9 channel RF RX/TX,i want to connect 3 motors to it.I am able to connect channel 1 with motor1 but unable to connect channel2 with motor2 simultaneously with ardunio.Pls take a look at code. cant able to rotate motors with different channels
int motor1Left = 7;// defines pin 5 as connected to the motor
int motor1Right= 9;// defines pin 6 as connected to the motor
int motor2Left = 22;// defines pin 7 as connected to the motor
int motor2Right = 26;// defines pin 8 as connected to the motor
int enable = 5;
int enable2 = 10;
int channel1 = 2; // defines the channels that are connected
int channel2 = 3;// to pins 9 and 10 of arduino respectively
int Channel1 ; // Used later to
int Channel2 ; // store values
void setup ()
{
pinMode (motor1Left, OUTPUT);// initialises the motor pins
pinMode (motor1Right, OUTPUT);
pinMode (motor2Left, OUTPUT);
pinMode (motor2Right, OUTPUT);// as outputs
pinMode (channel1, INPUT);// initialises the channels
pinMode (channel2, INPUT);// as inputs
//pinMode (enable, OUTPUT);
Serial.begin (9600); // Sets the baud rate to 9600 bps
}
void loop ()
{
Channel1 = (pulseIn (channel1, HIGH)); // Checks the value of channel1
Serial.println (Channel1); //Prints the channels value on the serial monitor
delay(1000);
Channel2 = (pulseIn (channel2, HIGH)); // Checks the value of channel1
Serial.println (Channel2); //Prints the channels value value on the serial monitor
delay(1000);
if (Channel1 > 1470 && Channel1 < 1500) /*If these conditions are true, do the following. These are the values that I got from my transmitter, which you may customize according to your transmitter values */
{
digitalWrite (motor1Left, LOW); // Sets both the
digitalWrite (motor1Right, LOW);// motors to low
analogWrite(enable, 100);
}
if (Channel1 < 1460) // Checks if Channel1 is lesser than 1300
{
digitalWrite (motor1Left, HIGH);// Turns the left
digitalWrite (motor1Right, LOW); // motor forward
analogWrite(enable, 100);
//delay(500);
//delay(500);
//digitalWrite(motor1Left, LOW);
//delay(1);
}
if (Channel1 > 1510) // Checks if Channel1 is greater than 1500
{
digitalWrite (motor1Left, LOW);// Turns the right
digitalWrite (motor1Right, HIGH);// motor forward
analogWrite(enable, 70);
//delay(500);
//digitalWrite (motor1Right, LOW);
// delay(50);
//digitalWrite (motor1Right, HIGH);
}
if (Channel2 > 1480 && Channel1 < 1500 ) // If these conditions are true, do the following
{
digitalWrite (motor2Left, LOW);// Sets both the
digitalWrite (motor2Right, LOW);// motors to low
analogWrite (enable2, 100);
}
if (Channel2 < 1300) // Checks if Channel2 is lesser than 1300
{
digitalWrite (motor2Left, LOW);// Turns the left
digitalWrite (motor2Right, HIGH);// motor backward
analogWrite (enable2, 100);
}
if (Channel2 > 1500) // Checks if Channel2 is greater than 1500
{
digitalWrite (motor2Left, HIGH);// Turns the right
digitalWrite (motor2Right, LOW);// motor backward
analogWrite (enable2, 100);
}
}
I see a couple of problems:
You mention 3 motors, but there appear to be only 2.
You print out th value read, but don't have any help to identify which one. Consider adding "Serial.print("Ch1 = ");" just before the first println to differentiate.
About line 72, you are have mixed Channel2 and Channel1.
In both channels, you have some dead zones for your readings. For example, for Channel 1, what will happen if Channel1 is 1465? Or 1460 or 1470? In all those cases none of your "if" statements will fire. In Channel2 the lower dead zone is much bigger, and the upper dead zone is still there (what if Channel2 is exactly 1500?).
Lastly, it still seems like your motor should have done something. Maybe it was because Channel 1 was less than 1500. But if it still doesn't work, check your wiring.
Also, a style note: You use channel1 to be the input pin to read. You use Channel1 to be the value read from that. These are extremely similar looking. If you had mistyped one, it would be almost impossible to spot. You should consider naming these in a way that makes it easier to spot a mistake, and more obvious. For example, channel1 could become pinCh1, and Channel1 could become inpCh1. Others might suggest even more descriptive names, possibly with the first letter indicating data type. e.g.,
int iChannel1_PinNumber;
int iChannel1_InputValue;
Related
I'm trying to measure the discharge time of a capacitor using a NodeMCU board. See complete sketch below. This code works fine, however I want to improve it to get to better time scales, by using the ESP.getCycleCount() function and interrupts for the timing. The part of interest is this:
startTime = micros();
while (digitalRead(capPos) == HIGH) {
delayMicroseconds (1);
}
endTime = micros();
The while loop I want to rewrite into some form of interrupt based function, listening to a falling edge of the capPos pin, replacing the above function with something like this:
startTime = micros();
attachInterrupt(digitalPinToInterrupt(capPos), dischargeInterrupt, FALLING);
}
void dischargeInterrupt() {
endTime = micros();
detachInterrupt(digitalPinToInterrupt(capPos));
After that the original code continues.
Te problem I have is how to take the required 100 samples. When setting the interrupt after the startTime is taken, this routine will finish and do the next of the 100 iterations. Instead it should wait: for the interrupt to come, then for the rest of the routine to finish, as per original sketch. Being rather new to interrupts, I have no idea where to start with that part.
So what has to be done:
- loop() calls getEC()
getEC() takes 100 samples:
charge the cap, set the pins for discharge, set interrupt to measure discharge time.
interrupt comes, time passed is measured. Negative cap cycle is performed and one sampling round complete.
The main purpose of this change is to make the timing more accurate: react instantly on pin dropping to LOW and use a much higher resolution for time. The current microsecond resolution does the job but it's a serious limitation.
Here my complete, working, sketch:
// capacitor based TDS measurement
// pin D5 C+ - 330 ohm resistor----------|------------|
// | |
// cap EC probe or
// | resistor (for simulation)
// pin D6 C- ----------------------------| |
// |
// pin A0 EC -----------------------------------------|
#include <Average.h>
int capPos = D5; //C+
int capNeg = D6; //C-
int EC = D7; //EC
float CAP = 47; // capacity in nF
#define calibration 150 // a calibration factor to link time with EC.
void setup() {
Serial.begin(9600);
}
void loop () {
float EC = getEC(); // get the EC as mS/cm.
Serial.println (", EC: " + String(EC) + " mS/cm");
delay(100);
}
float getEC() {
int samples = 100; // number of EC samples to take and average.
unsigned long startTime; // the time stamp (in microseconds) the measurement starts.
unsigned long endTime; // the time stamp (in microseconds) the measurement is finished.
unsigned int dischargeTime; // the time it took for the capacitor to discharge.
Average<unsigned int> discharge(samples); // Take measurements on both the positive and negative cycles.
unsigned int chargeDelay = 500; // The time (in microseconds) given to the cap to fully charge/discharge - about 10x RC is a good value.
int startLevel; // analog level of the pin.
int endLevel;
pinMode(A0, INPUT);
for(int i=0; i<samples; i++) { // take <samples> measurements of the EC.
// Stage 1: fully charge capacitor for positive cycle.
// C+ high, C- low, EC disconnected.
pinMode (EC, INPUT);
pinMode (capPos,OUTPUT);
digitalWrite (capPos, HIGH);
pinMode (capNeg, OUTPUT);
digitalWrite (capNeg, LOW);
delayMicroseconds(chargeDelay);
// Stage 2: positive side discharge; measure time it takes.
// C+ disconnected, C- low, EC low.
pinMode (capPos,INPUT); //set C+ to input to keep voltage from grounding a discharging thru this output pin
pinMode (EC, OUTPUT);
digitalWrite (EC, LOW);
// Measure time until capPos goes LOW. Can't use pulseIn() here as the pin will be high already.
startTime = micros();
while (digitalRead(capPos) == HIGH) {
delayMicroseconds (1);
}
endTime = micros();
// handle potential overflow of micros() just as we measure, this happens every 70 minutes.
if (endTime < startTime) dischargeTime = 4294967295 - startTime + endTime;
else dischargeTime = endTime - startTime;
discharge.push(dischargeTime);
// Stage 3: fully charge capacitor for negative cycle. C+ low, C- high, EC disconnected.
pinMode (EC, INPUT);
pinMode (capPos,OUTPUT);
digitalWrite (capPos, LOW);
pinMode (capNeg, OUTPUT);
digitalWrite (capNeg, HIGH);
delayMicroseconds(chargeDelay);
// Stage 4: negative side charge; don't measure as we just want to balance it the directions.
// C+ disconnected, C- low, EC low.
pinMode (capPos,INPUT); //set C+ to input to keep voltage from grounding a discharging thru this output pin
pinMode (EC, OUTPUT);
digitalWrite (EC, HIGH);
delayMicroseconds(dischargeTime);
}
float dischargeAverage = discharge.mean();
Serial.print("Discharge time: ");
Serial.print(dischargeAverage);
// Calculate EC from the discharge time.
return dischargeAverage;
}
So, got this answered myself.
For the time resolution: you can get a much more exact time by using ESP.getCycleCount() which counts processor cycles - on my 80 MHz NodeMCU board that's 12.5 ns per cycle or 80 cycles per microsecond. I should have mentioned that in the first part.
Interrupts: this is something I misunderstood. Now I solved it by having the main function wait in a loop until a timeout is reached (set to 1 millisecond, normal expected times are in the 1-100 microseconds range), or until a global variable is set by the interrupt function. So now I'm measuring in the 12.5 nanosecond resolution!
One thing that's missing from this sketch is a correction for program time taken to deal with the timing: the time it takes from dropping the value on the EC pin to starting to count, and the time it takes from receiving the interrupt to stopping the count. If that overhead is say 100 cycles, that would be 1.25 microseconds, which is well within my measurement time.
// capacitor based TDS measurement
// pin D5 C+ - 330 ohm resistor----------|------------|
// | |
// cap EC probe or
// | resistor (for simulation)
// pin D6 C- ----------------------------| |
// |
// pin A0 EC -----------------------------------------|
#include <Average.h>
int capPos = D5; //C+
int capNeg = D6; //C-
int EC = D7; //EC
unsigned long startCycle;
unsigned long endCycle;
#define CYCLETIME 12.5 // the time it takes in nanoseconds to complete one CPU cycle (12.5 ns on a 80 MHz processor)
float CAP = 47; // capacity in nF
#define calibration 150 // a calibration factor to link time with EC.
void setup() {
Serial.begin(9600);
}
void loop () {
float EC = getEC(); // get the EC as mS/cm.
Serial.println (", EC: " + String(EC) + " mS/cm");
delay(500);
}
float getEC() {
int samples = 100; // number of EC samples to take and average.
unsigned long startTime; // the time stamp (in microseconds) the measurement starts.
unsigned long endTime; // the time stamp (in microseconds) the measurement is finished.
unsigned int dischargeTime; // the time it took for the capacitor to discharge.
Average<unsigned int> discharge(samples); // The sampling results.
unsigned int chargeDelay = 500; // The time (in microseconds) given to the cap to fully charge/discharge - about 10x RC is a good value.
unsigned int timeout = 1; // discharge timeout in milliseconds - if not triggered within this time, the EC probe is probably not there.
int startLevel; // analog level of the pin.
int endLevel;
pinMode(A0, INPUT);
for(int i=0; i<samples; i++) { // take <samples> measurements of the EC.
// Stage 1: fully charge capacitor for positive cycle.
// C+ high, C- low, EC disconnected.
pinMode (EC, INPUT);
pinMode (capPos,OUTPUT);
digitalWrite (capPos, HIGH);
pinMode (capNeg, OUTPUT);
digitalWrite (capNeg, LOW);
delayMicroseconds(chargeDelay);
// Stage 2: positive side discharge; measure time it takes.
// C+ disconnected, C- low, EC low.
startCycle = ESP.getCycleCount();
pinMode (capPos,INPUT); //set C+ to input to keep voltage from grounding a discharging thru this output pin
pinMode (EC, OUTPUT);
digitalWrite (EC, LOW);
// Use cycle counts and an interrupt to get a much more precise time measurement, especially for high-EC situations.
endCycle = 0;
startTime = millis();
attachInterrupt(digitalPinToInterrupt(capPos), capDischarged, FALLING);
while (endCycle == 0) {
if (millis() > (startTime + timeout)) break;
}
detachInterrupt(digitalPinToInterrupt(capPos));
if (endCycle == 0) dischargeTime = 0;
else {
// Handle potential overflow of micros() just as we measure, this happens about every 54 seconds
// on a 80-MHz board.
if (endCycle < startCycle) dischargeTime = (4294967295 - startCycle + endCycle) * CYCLETIME;
else dischargeTime = (endCycle - startCycle) * CYCLETIME;
discharge.push(dischargeTime);
}
// Stage 3: fully charge capacitor for negative cycle. C+ low, C- high, EC disconnected.
pinMode (EC, INPUT);
pinMode (capPos,OUTPUT);
digitalWrite (capPos, LOW);
pinMode (capNeg, OUTPUT);
digitalWrite (capNeg, HIGH);
delayMicroseconds(chargeDelay);
// Stage 4: negative side charge; don't measure as we just want to balance it the directions.
// C+ disconnected, C- high, EC high.
pinMode (capPos,INPUT); //set C+ to input to keep voltage from grounding a discharging thru this output pin
pinMode (EC, OUTPUT);
digitalWrite (EC, HIGH);
delayMicroseconds(dischargeTime/1000);
}
float dischargeAverage = discharge.mean();
Serial.print("Discharge time: ");
Serial.print(dischargeAverage);
// Calculate EC from the discharge time.
return dischargeAverage;
}
// Upon interrupt: register the cycle count of when the cap has discharged.
void capDischarged() {
endCycle = ESP.getCycleCount();
detachInterrupt(digitalPinToInterrupt(capPos));
}
functionality:
Arduino make use of the following:
1. IR sensor
2. LED Light
3. MotorFan
4. Relay
hence, when user approaches the IR sensor, it will give a serialPrint of '1' since it has detected proximity, this will then toggle the state of LED and motorfan from LOW to HIGH. However, after 5s, the state of motorfan will toggle to LOW from HIGH, while the state of LED will still remain HIGH and will remain as HIGH as long as the serialPrint is '1'.
However, when user leaves the proximity of the IR sensor, the LED state will toggle to LOW from HIGH after 10s.
What I have done:
Code that I have done:
const int signalPin = 1; //wire pin to analog for IR Sensor
//Motor-Fan Relay
byte FanRelay = 4;
byte LightRelay = 6;
int IRSignal; //variable signal, will hold the analog value read by Arduino
long duration;
int distance;
unsigned long Timer;
unsigned long Interval = 10000; //teh repeat Interval
unsigned long MotorFanOff = 5000;
void setup()
{
//Execute only once at startup
//pinMode (FanPin , OUTPUT) ; // Set pinMode for FanPin as OUTPUT, display
pinMode (signalPin, INPUT); //infared sensor line will be an input to the Arduino
pinMode(FanRelay, OUTPUT);
pinMode(LightRelay, OUTPUT);
Serial.begin(9600); // Open serial port to communicate with the Ultrasaonic Sensor
}
void loop()
{
//execute multiple times in a loop
IRSignal = analogRead(signalPin); //arduino reads the value from the infared sensor
distance = 9462 / (IRSignal -16.92);
if(distance < 30 && distance > 0)
{
Timer = millis();
// Write a pin of HIGH
Serial.println("1");
//Set motor-fan to operate
digitalWrite (FanRelay, HIGH);
digitalWrite (LightRelay, HIGH);
//After a delay of 5s, MotorFan will toggle to LOW
//Toggle MotorFan to LOW after 5s
if ((millis()-Timer)>MotorFanOff){
digitalWrite (FanRelay, LOW);
}
}
else
{
Serial.println("0");
//Check if Timer is longer than 10s
if ((millis()-Timer)>Interval){
digitalWrite (LightRelay, LOW);
digitalWrite (FanRelay, LOW);
}
}
delay(1000);
}
Issue:
At this point, when tested, both the state of the LED and motorfan will toggle from LOW to HIGH when the serialPrint is '1' from the IR sensor. However, the main issue that i am facing is that the state of the MOTORFAN does not toggle to LOW from HIGH after 5seconds, but both state will only toggle to LOW when serialPrint is '0'.
Hence, what have I done wrong? pls help.thanks.
Be careful! The first two pins on the Arduino are used for serial communication and break if you use them for something else. Switch over to higher pin numbers and the problem should go away.
I'm trying to generate pulse from Arduino to driver motor stepper 5 phase.
The driver only needs pulse to make motor stepper work. My problem is when I'm using code like this
for(int i=0; i <= 125; i++)
{
//analogWrite(13,125);
digitalWrite(13, HIGH);
delayMicroseconds(300);
digitalWrite(13, LOW);
delayMicroseconds(300);
}
digitalWrite(13,LOW);
delay(3000);
Stepper motor can work perfectly, but after more than 10 rotation,
the angle of the motor did not return to the original place. Can we use pwm in Arduino like that? So after generating 5000 pulses using pwm, we stop the pwm?
try this code:
#include <TimerOne.h>
const byte CLOCKOUT = 11;
volatile byte counter=0;
void setup() {
Timer1.initialize(15); //Every 15 microseconds change the state of the pin in the wave function giving a period of 30 microseconds
Timer1.attachInterrupt(Onda);
pinMode (CLOCKOUT, OUTPUT);
digitalWrite(CLOCKOUT,HIGH);
}
void loop() {
if (counter>=6000){ //With 6000 changes you should achieve the amount of pulses you need
Timer1.stop(); //Here I create the dead time, which must be in HIGH
PORTB = B00001000;
counter=0;
delayMicroseconds(50);
Timer1.resume();
}
}
void Onda(){
PORTB ^= B00001000; //Change pin status
counter+=1;
}
I just cant not eliminate the jitter. If you find a solution let me know
I am doing a basic project in Arduino UNO connecting an Ultra Sonic sensor (HC-SR04) which should print in the serial monitor the distance of the closest object but it always print 0.
This is my code:
long distance;
long time;
void setup(){
Serial.begin(9600);
pinMode(4, OUTPUT);
pinMode(2, INPUT);
}
void loop(){
digitalWrite(2,LOW);
delayMicroseconds(5);
digitalWrite(2, HIGH);
delayMicroseconds(10);
time = pulseIn(4, HIGH);
distance = int(0.017*time);
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm.");
delay(1000);
}
And this is the breadboard:
The primary issue that I see is that your code doesn't match your wiring diagram.
For example, your diagram shows Trig connected to pin 4. The Trig should be the output from your Arduino but you have it defined as an input.
The Echo is connected to pin 2 and it should be an input, but you have it defined as an output.
Finally, in your loop(), you are not even using pin 2 or pin 4, but pins 9 and 8. Another issue is the timing you use in setting the trigger pulse - it does not match the datasheet. I would do something like this (assuming that you are actually connected to the pins shown in your diagram):
#define sensorTrigPin 4
#define sensorEchoPin 2
void setup()
{
Serial.begin(9600);
pinMode(sensorTrigPin, OUTPUT);
pinMode(sensorEchoPin, INPUT);
}
void loop()
{
int pulseWidth = 0;
digitalWrite(sensorTrigPin, HIGH);
delayMicroseconds(10);
digitalWrite(sensorTrigPin, LOW);
pulseWidth = pulseIn(sensorEchoPin, HIGH);
Serial.print("Pulse Width: ");
Serial.print(pulseWidth);
delay(1000);
}
Note that pulseWidth is just the amount of time that it takes from the beginning of the Echo pulse going high to the end of the same pulse (when it goes low). You would still have to calculate the distance based on the value of pulseWidth.
UPDATE BASED ON RECENT EDIT TO THE QUESTION
If you change a portion of your loop() code to this, it should work:
void loop(){
digitalWrite(4, HIGH); //was (2, LOW)
delayMicroseconds(10); //was (5)
digitalWrite(4, LOW); //was (2, HIGH)
//REMOVED EXTRA DELAY
time = pulseIn(2, HIGH); //was (4,HIGH);
... //Keep the rest of your code the same.
}
Try connecting your VCC of the sensor to 3V3 instead of 5V. This might sound odd, but I tried it and it worked well. Also, please make sure that your echo and trig pin match the code.
My Arduino board is Arduino Due ATmega328p. My Ultrasound is srf05.
I measure the distance is 5cm but my serial show me "531".Serial Monitor show the int of distance which value is always be 531.Why?
Here are the codes.
#define ECHOPIN 2 // Pin to receive echo pulse
#define TRIGPIN 3 // Pin to send trigger pulse
void setup(){
Serial.begin(9600);
pinMode(ECHOPIN, INPUT);
pinMode(TRIGPIN, OUTPUT);
}
void loop(){
digitalWrite(TRIGPIN, LOW); // Set the trigger pin to low for 2uS
delayMicroseconds(2);
digitalWrite(TRIGPIN, HIGH); // Send a 10uS high to trigger ranging
delayMicroseconds(10);
digitalWrite(TRIGPIN, LOW); // Send pin low again
int distance = pulseIn(ECHOPIN, HIGH); // Read in times pulse
distance = distance/58; // Calculate distance from time of pulse
Serial.println(distance);
delay(50); // Wait 50mS before next ranging
}
The srf05 times out if it doesn't receive the echo pulse. The width of the pulse is 30 ms.
30,000 / 58 is 517, which is close to 531. It looks like your device is not receiving an echo from the object. This makes your problem a hardware issue, and not a programming issue. (The code looks correct.)