Arduino - I need to alter my code to insert a delay - arduino

I am running an Arduino Nano (with a RasPi to send to Thingspeak). It measures different things in my office, temp, hum, CO2 AND it waters my plant. :-)
I have a small problem with my code for the plant watering.
Here is what I want it to do:
Loop
Measure Soil moisture
If > 60 run pump for 2 seconds
Delay 180 seconds (this delay goes for all sensors)
I have a problem! This is what the code actually does:
Loop
Measure Soil moisture
If > 60 run pump for 2 seconds
This means that it just keeps watering away, much faster than the water can absorb the water.
Please help me get the delay working.
Thank you. :-)
This is the code I am running:
void loop()
{
int temp = 0, hum = 0, moist = 0, level = 0, co2_ppm = 0;
moist = read_soil_moisture(soil_pin);
temp = read_temp();
hum = read_humidity();
level = read_water_level(water_pin);//reads water level
co2_ppm = CO2_PPM();
//print_sensor(hum, temp, moist, level,co2_ppm);
temp = read_temp();
if (temp >= 3)
{
temp -= 3;
}
else
{
temp = 0;
}
log_sensor(hum, temp, moist, level, co2_ppm); //prints values of sensors to UART
if (moist > 60)
{
digitalWrite(pump, LOW);//Setting relay pin high
delay(2000);//keeps relay pin high for 2 seconds
digitalWrite(pump, HIGH);//Setting relay pin low
}
else
{
digitalWrite(pump, HIGH);//keep relay pin low
}
delay(180000);//take a reading every 180 seconds
Github repo: https://github.com/pkold/Self-watering-plant-system

Do you have readings from the moisture sensor when it is complete dry and when it is fully emerged in water?
When i look at your github repo the moisture value is a percentage which increase when the moisture rises.
Turning on the pump when the moisture is already above 60 will only increase the sensor value.

Related

Arduino, HC SR-04 distance sensor wrong output

my name is Dmitrij and I wanted to connect HC-SR04 to Arduino so that I can measure the distance.
The problem is that the sensor is sending 4-5 right results and then 5-6 wrong ones in a row.
I've tried to replace Arduino and the sensor it didn't help.
At the end while I was writing this I kinda solved the problem.
The sensor was getting 5 Volt from external powersuply module (https://i.imgur.com/Zjg22ka.png) after I connected sensor to Arduino 5V everything was working Fine.
Is there a way to fix this somehow?
int echo = 8;
int trig = 9;
float duration, distance;
void setup() {
pinMode(echo, INPUT);
pinMode(trig, OUTPUT);
digitalWrite(trig, LOW);
Serial.begin (9600);
}
void loop() {
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
duration = pulseIn(echo, HIGH);
distance = (duration / 2) * 0.0344;
Serial.print("Distance = ");
Serial.print(distance);
Serial.println(" cm");
delay(500);
}
Thats the output of the sensor when it was directed on the wall.
The real Distance is around 15-16 cm and i don't understand why does it output something else also.
Distance = 15.70 cm
Distance = 15.70 cm
Distance = 15.65 cm
Distance = 15.70 cm
Distance = 3.92 cm
Distance = 2.25 cm
Distance = 1.67 cm
Distance = 0.48 cm
Distance = 0.55 cm
Distance = 6.73 cm
Distance = 15.65 cm
Distance = 15.65 cm
Distance = 15.65 cm
Distance = 15.65 cm
Distance = 4.11 cm
Distance = 2.27 cm
Distance = 1.50 cm
Distance = 0.50 cm
Distance = 0.50 cm
Distance = 6.33 cm
and so on.
It depends on how curvy your scanned surface is, some times it can give you the wrong information, try scanning a flat surface and take a look your output will be.
Can you follow these steps ? I had same problem and I connected trig and echo pin as shown in link and worked.
Don't forget that you have to download NewPing library
If not worked, you should check all the cables.

Flat top Pulse Amplitude Modulation

i want to plot flat-topped PAM of sinusoid. wave using matlab.
the sinusoidal signal has frequency = 10^4/(2*pi) HZ and sampling frequency = 8 kHZ. pulse duration T = 50 microseconds.
i wrote code for natural sampling, so how to do flat-top?
clear all;
close all;
Fs = 1e9;
t = 0:1/Fs:(0.2e-2);
fc = 8000; %sampling frequency
fm = 10^4/(2*pi); %message frequency
a = 1;
vm = a.*sin(2*pi*fm*t); %message
pulseperiods = [0:10]*1/fc;
pulsewidth = 50e-6;
vc = pulstran(t,pulseperiods,#rectpuls,pulsewidth);
y = vc.*vm;
figure
subplot(3,1,1);
plot(t,vm); % plot message
xlabel('Temps');
ylabel('Amplitude');
title('Message');
subplot(3,1,2);
plot(t,vc); % plot pulse
xlabel('Temps');
ylabel('Amplitude');
title('Switching waveform');
subplot(3,1,3);
plot(t,y); % plot PAM naturel
xlabel('Temps');
ylabel('Amplitude');
title('PAM naturel');
The flat-top PAM means the instantaneous sampling, i.e. the message signal is sampled only once per period, so modulated signal does not change its value until returning to zero and next sampling period. The sampling takes place at rising edge of carrier signal, so the solution is quite straightforward: by adding the for loop to your code:
for i = 2:length(t)
if vc(i) == 1 && vc(i-1) == 0 %if the rising edge is detected
y1(i) = vc(i) * vm(i); %sampling occurs
elseif vc(i) == 1 && vc(i-1) == 1 %and while the carrier signal is 1
y1(i) = y1(i-1); %the value of y1 remains constant
else
y1(i) = 0; %otherwise, y is zero
end
end
plot(t,y1); % flat-top PAM plot
xlabel('Temps');
ylabel('Amplitude');
title('PAM flat-top');
you get

analogread() function in a for loop

I have 6 sensors connected to the pin A0, A1, A2, A3, A4, A5 and I am trying to get readings from each sensor. I have a analogread() function inside of a for loop and it does not work.
If I just trigger the sensor at A0, all other sensors will have the same reading as that one even if they are not triggered. I used a voltage meter to test the voltage of each pin and only got voltage at A0 when the A0 sensor is triggered. So I believe this is a coding problem.
Here is my code:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0~5:
for(int i = 0; i < 6; i++){
int sensorValue0 = analogRead(i);
delay(700);
// Convert the analog reading (which goes from 0 - 1023) to voltage range (0 - 5V);
float voltage0 = sensorValue0 * (5.0 / 1023.0);
// print out the value you read:
Serial.print(voltage0);Serial.print(" i = ");
Serial.print(i);Serial.print(" ; ");
if (i == 5) Serial.println(" ");
}
}
I just set up some voltage dividers, consisting of combination of various R1 and R2=1k and hooked them up to the analog inputs of an Arduino. Using your code, I received the following data (S0 = raw reading, V0 = calculated voltage)
R1 S0 V0
220 841 4.11
470 695 3.40
1k 511 2.50
2k2 318 1.55
4k7 179 0.87
6k8 128 0.63
This looks fine. Your code is correct. There's definitely something wrong with your wiring.

Arduino and RC Transmitter

I am new to Arduino and to this forum and this is my first Arduino project besides the tutorials.
I am trying to control a servo using a rc transmitter/receiver and the Arudino. The reason why I am using a Arduino instead of connecting the servo directly to the RC receiver is that the RC can only generate a PWM of 1000µs to 2000µs while I need a PWM of 600µs to 2400µs to get the full range of motion of my servo. What I have tried to do is to read the value from pulseIn(), then mapping this value to 0 to 180 degree as written in code below (which utilizes servo library).
However, with this code, the motor behaviour is weird. As I move the radio transmitter control stick through its range of motion, the motor rotates from 0 to 45 degrees, back from 45 to 0, 0 to 45, and back to 0 again instead of sweeping from 0 to 180 degrees. Could anyone please offer some help or advice?
Thank you very much
#include <Servo.h>
Servo myservo;
int ch1;
int ch2;
int ch3;
int degree;
void setup() {
pinMode(7, INPUT);
myservo.attach(9);
Serial.begin(9600);
}
void loop() {
ch3 = pulseIn(7, HIGH, 25000);
degree = ((ch3-1250)* 180)/700;
Serial.print("Channel 3:");
Serial.println(ch3);
myservo.write(degree);
delay(5); // waits 5ms for the servo to reach the position
}
You are overflowing the int data type. The signed value can only be -32768 to +32767. See int docs
Your formula is all int's and the compiler will not guess that you might need a larger intermediate value. The multiply by 180 is a red flag. (2000-1250)*180 = 135000 = boom
To understand the math, break down a formula into the individual operations as shown in the test program below. That is essentially what the compiler is doing for you.
Run the program below and you will see the failure. Just after the out value reaches 45, the intermediate value overflows and the formula breaks down.
in: 1040 out: 39 t0: -210 t1: 27736 t2: 39
in: 1048 out: 41 t0: -202 t1: 29176 t2: 41
in: 1056 out: 43 t0: -194 t1: 30616 t2: 43
in: 1064 out: 45 t0: -186 t1: 32056 t2: 45
in: 1072 out: -45 t0: -178 t1: -32040 t2: -45
in: 1080 out: -43 t0: -170 t1: -30600 t2: -43
Use this program below as a test fixture. Modify the data types to use unsigned int and you will be able to make the output behave as you need.
int ch3;
int degree;
void setup() {
ch3 = 1000;
Serial.begin(9600);
}
void loop() {
int t0, t1, t2;
degree = ((ch3-1250)* 180)/700;
t0 = ch3 - 1250;
t1 = t0 * 180;
t2 = t1 / 700;
Serial.print("in: ");
Serial.print(ch3);
Serial.print(" out: ");
Serial.print(degree);
Serial.print(" t0: ");
Serial.print(t0);
Serial.print(" t1: ");
Serial.print(t1);
Serial.print(" t2: ");
Serial.println(t2);
ch3 += 8;
if(ch3 > 2400) {
ch3 = 1000;
}
delay(100);
}
As a note, you may have more Arduino/servo luck on https://robotics.stackexchange.com/.
What are you seeing on the serial output? Is ch3 cycling from 0 to 45 or from 0 to 180? Don't forget that map() is designed to do what you're doing by hand here.
My first suspicion is that you're occasionally getting 0 back from pulseIn either because you're timing out, or you're starting your reading in the middle of a pulse (which could lead to a shorter pulse than you expect).

Arduino temperature sensor

I am trying to build a small program with arduino using a temperature-sensor.
I thought I knew how to do it but I'm getting some weird outputs.
Here is my code:
int sensorPin = 0;
void setup()
{
Serial.begin(9600);
}
void loop()
{
int reading = analogRead(sensorPin);
float voltage = reading * 5.0 / 1024;
float temperatureC = (voltage - 0.5) * 100;
Serial.print(temperatureC); Serial.print(" degrees C, ");
Serial.print(voltage); Serial.println(" volts");
delay(1000);
}
This code gives me the output:
-26.56 degrees C, 0.23 volts
-26.56 degrees C, 0.23 volts
-27.05 degrees C, 0.23 volts
-26.56 degrees C, 0.23 volts
-26.07 degrees C, 0.24 volts
-26.07 degrees C, 0.24 volts
Why is it - in degrees? and Why can I change it to any pin I want and it will still give me a similar output?
Analog input 0 is not pin 0.
You should use the defined symbols:
A0,A1,...,A7
for analog inputs.
Try
int sensorPin = A0;
and your program should work.
If you are curious about the actual values, under your Arduino IDE install look in the file
..\hardware\arduino\variants\standard\pins_arduino.h
You are reading this input correctly.
In order for you to not get negative degrees, you'll have to process it differently.
With this:
float temperatureC = (voltage - 0.5) * 100;
Any values < 0.5 result in multiplying a negative number by 100.
Try breaking this down using commutative property.
(voltage - 0.5) * 100 is the same as (voltage * 100) - (0.5 * 100).
This can be further simplified to (voltage * 100) - 50.
Still, for all values where voltage < 0.5 the temperature will be negative.
I would suggest multiplying temperatureC by -1 to make it positive and not putting the sensor near anything that is `~ >= 50 degrees Celsius.
Also, As jdr5ca pointed out here, you're not actually getting any data from the sensor yet... :(
You are probably getting noise (or garbage) from whatever pin0 is.
EDIT
It is best practice to use parentheses to make order of operations more clear.
ie:
float voltage = reading * 5.0 / 1024;
should be
float voltage = reading * (5.0 / 1024);
First, you have to use the defined symbols A0
int sensorPin = A0;
in the next
float voltage = reading * (5.0 / 1024);
There is an example in File/Examples/Basic/AnalogReadSerial

Resources