analogread() function in a for loop - arduino

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.

Related

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

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.

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.

How to use Multiple mcp23017 chips with the adafruit mcp23017.h library

I have been experimenting with I2C and the mcp23017 IO expander chip for my arduino ATMega2560 as I would rather use the IO on the arduino its self for other things I am just figuring out how to use the adafruit mcp23017.h library and cant figure out how to address multiple mcp23017 chips and how to use there pins individually this is the code from the button library that I editied.
I want to be able to address the individual chips and the pins I was not quite sure if in the setup that the pin modes for the IO go up sequentially from 0 past 15 if multiple chips are connected and addressed in code. For example if the first chip is addressed as 0x20 and the IO number count is from 0 - 15 if I added and addressed another chip as 0x21 will that count go from 0 - 15 to 0 - 31.
#include <Wire.h>
#include "Adafruit_MCP23017.h"
//pin 1 and 0 are mcp pins not arduino IO pins
Adafruit_MCP23017 mcp;
void setup() {
mcp.begin(); // use default address 0
mcp.pinMode(0, INPUT);
mcp.pinMode(1, OUTPUT);
Serial.begin(9600);
pinMode(13, OUTPUT); // use the p13 LED as debugging
}
void loop() {
// The LED will 'echo' the button
digitalWrite(13, mcp.digitalRead(0)); //Writes pin 13 to the reading of pin 0
mcp.digitalWrite(1, mcp.digitalRead(0)); //Writes pin 1 to the reading of 0
if(mcp.digitalRead(1) == HIGH){ //if pin 1 == high serialprint led whent high
Serial.println("Led whent HIGH");
}
}
Every chip must have unique address, and this is doable according to Microchip's manual page 8. So, first of all, you should setup different addresses in your hardware layout.
You should also create an Adafruit_MCP23017 object for every chip you want to use, and setup corresponding addresses in your code.
In this case pins of all chips will have addresses in range 0-15. To change pin's state you should reference to particular instance.
Update
This is starting point for you
#include "Adafruit_MCP23017.h"
Adafruit_MCP23017 mcp1;
Adafruit_MCP23017 mcp2;
Adafruit_MCP23017 mcp3;
#define addr1 0x00
#define addr2 0x01
#define addr3 0x02
void setup() {
mcp1.begin(addr1);
mcp2.begin(addr2);
mcp3.begin(addr3);
}
void loop() {
}
I share my solution with 7 MCP23017 chip , 7x14 pins=98 pins using adafruit library.
Connections:
addr 0 = A2 low , A1 low , A0 low 000
addr 1 = A2 low , A1 low , A0 high 001
addr 2 = A2 low , A1 high , A0 low 010
addr 3 = A2 low , A1 high , A0 high 011
addr 4 = A2 high , A1 low , A0 low 100
addr 5 = A2 high , A1 low , A0 high 101
addr 6 = A2 high , A1 high , A0 low 110
addr 7 = A2 high, A1 high, A0 high 111
Connect pin #12 of the expander to Analog 5 (i2c clock)
Connect pin #13 of the expander to Analog 4 (i2c data)
Connect pins #15, 16 and 17 of the expander to ground (address selection)
Connect pin #9 of the expander to 5V (power) // operation voltage is 1.8 to 5.5
Connect pin #10 of the expander to ground (common ground)
Connect pin #18 through a ~10kohm resistor to 5V (reset pin, active low)
Input #0 is on pin 21 so connect a button or switch from there to ground
Code:
#include <Adafruit_MCP23017.h>
Adafruit_MCP23017 mcp1; // chip 1
Adafruit_MCP23017 mcp2; // chip 2
#define addr1 7 // 7 = A2 high, A1 high, A0 high
#define addr2 0 // 0 = A2 low, A1 low, A0 low
void setup()
{
Serial.begin(9600);
mcp1.begin(addr1);
mcp2.begin(addr2);
mcp1.pinMode(0, INPUT); //pin 21 on chip
mcp2.pinMode(0, INPUT); //pin 21 on chip
}
void loop()
{
if(mcp1.digitalRead(0)== HIGH )
Serial.println("HIGH");
delay(1000);
if(mcp2.digitalRead(0)== HIGH )
Serial.println("HIGH 2");
delay(1000);
}
I finally got my code to work! in the end it was simpler than i though and i probably did not give a good enough explanation of what my code was supposed to achieve this is my code here.
#include "Adafruit_MCP23017.h"
Adafruit_MCP23017 mcp1;
Adafruit_MCP23017 mcp2;
void setup() {
mcp1.begin(0);
mcp2.begin(1);
mcp1.pinMode(0, INPUT);
mcp1.pinMode(1, OUTPUT);
mcp2.pinMode(1, OUTPUT);
Serial.begin(9600);
pinMode(13, OUTPUT);
}
void loop() {
mcp2.digitalWrite(1, mcp1.digitalRead(0));
digitalWrite(13, mcp1.digitalRead(0));
mcp1.digitalWrite(1, mcp1.digitalRead(0));
if(mcp1.digitalRead(1) == HIGH){
Serial.println("Led whent HIGH");
}
}
The problem was that i had only declared 1 mcp and thanks to Vladimir Tsykunov I now know that I needed an mcp1 and mcp2 which can be now seen in my functional code I may run into problems in the future with stuff that i have not revised but for this project it is working now.

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