Using arduino analog inputs - arduino

I am creating my first Arduino program on the UNO r3. I have played with the Arduino Uno before just with petty example programs, etc. I am using two analog inputs to sense distance using 2 laser sensors with 0-5vdc scaling. These two inputs are 0-5vdc and I have ensured common grounding throughout. The two sensors are named left and right and are input to A0 and A1 respectively. I also have a differential POT which uses a 10K ohm POT wiper voltage as an input on A2. The theory of the program is to take the absolute value of the difference in input voltages between the left and right lasers then determine if the result is greater than or equal to the voltage on pin A2 from the POT wiper. Based on the resulting math, turn on or off a relay interposed to pin D13 via a transistor driver circuit.
The PROBLEM: I cannot achieve accurate changes in voltage on the scale (0-1023) on pins A0, A1, or A2. I have utilized the serial monitor to diagnose this problem. Not sure what the problem is, any help would be great. Also, I cannot achieve a 0 value on any of the above analog pins, even the POT wiper!!!
Here's my code:
const int lf_dist = A0; //names A0
const int rt_dist = A1; //names A1
const int differential = A2; //names A2
const int relay = 13; // select the pin for the relay coil
unsigned int left = 0; // variable to store the value coming from the left sensor
unsigned int right = 0; // variable to store the value coming from the right sensor
unsigned int diff = 0; // variable to store the value coming from the differential POT for maximum distance differential
unsigned int offset = 0; // variable that stores the value between the two laser sensors
void setup() {
Serial.begin(9600);
pinMode(A0, INPUT);
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode(relay, OUTPUT); // declare the relay pin as an OUTPUT:
analogReference(DEFAULT);
}
void loop()
{
unsigned int left = 0; // variable to store the value coming from the left sensor
unsigned int right = 0; // variable to store the value coming from the right sensor
unsigned int diff = 0; // variable to store the value coming from the differential POT for maximum distance differential
unsigned int offset = 0; // variable that stores the value between the two laser sensors
left = analogRead(A0); // read the value from the left laser
delay(5);
right = analogRead(A1); // read the value from the right sensor
delay(5);
diff = analogRead(A2); // read the value from the differential POT
delay(5);
offset = abs(left - right);
if(offset >= diff) // does math to check if left and right distances are greater than the value clocked in by the differential POT
{
digitalWrite(relay, LOW); // turns off the relay, opens the stop circuit, and turns on the yellow light
}
else
{
digitalWrite(relay, HIGH); // turns on the relay if all is good, and that keeps the machine running
}
Serial.print("\n left = " );
Serial.print(left);
Serial.print("\n right = " );
Serial.print(right);
Serial.print("\n differential = " );
Serial.print(diff);
delay(1000);
}

afaict, this should really be due to the floating pins surrounding the measuring pins, having erratic values, hence perturbating your measures. You should look at your values using arduinoscope, which will show you the interfering effects of the other floating pins on your measuring pins.
The easy workaround for this is to ground all analogical input pins you're not using, and put as much space as you can between both your inputs, so they don't interfere with each other.

I realize this thread is somewhat old not, but perhaps this will help someone. If you power the Arduino with only 5V, as you say you did with a regulator, you will get very erratic behavior, particularly from the analog pins. This is because you will start to brown out the internal voltage regulators that provide the AREF, 3.3, and 5.0 outputs. I've tested this for a robotics project I'm working on, and right around 6.5 volts, everything begins to go wrong. I suppose if you always provided 5.0 input voltage you could compensate for this effect, but in my case I used a LiPo battery that could range from 8.4 volts down to 6.0 volts, and everything goes crazy at 6.5 volts.

The minimum current that arduino sinks in during the sampling from potentiometer should not disturb the actual open input volts at the wiper.

Initialize the pins in pull up mode to avoid garbage values or 'floating' pins or use your own pull down/up resistors at the pins :)

Related

Arduino to generate a rising waveform (sine or triangle)

I would like to apply an increasing voltage and hold to my output from my arduino UNO. I realize that the arduino does not allow me to output analog values, and thus I decided to use an R2R ladder (with R- 22kohms and 2R- 47kohms). This would allow me to convert to an analog voltage. I made use of the eight digital pins on the arduino, to set up an 8 bit R2R ladder. I am able to output a sine wave, with my current setup, but a little bit unsure on how to output a wave which goes up to the maximum value and stops. (i.e. a wave like given in the picture below).
This wave is basically a triangle wave or even a sine wave which goes up to a max value and stays there (with 200 micro second pulse duration).
I have created a visual of my circuit to better demonstrate my problem:
I also attempted my problem, by outputting a sine wave. My code is as follows:
void setup() {
//set pins 0-7 as outputs
for (int i=0; i<8; i++){
pinMode(i, OUTPUT);
}
}
void loop() {
double value =0;
int check=0; int t=0;
while(check==0){
if (value<254){
value = 127+127*sin(2*3.14*t/100);
//this sends a sine wave centered around (127/255 * 5)=2.5V
//max will reach when t=25
PORTD=value;
delayMicroseconds(4); //wait 4 micro seconds
//this means that the max value will reach at ~25*6 =150 microseconds
}
else{
value =255;
PORTD=value; //just output the max of the sine wave (i.e. 255)
delayMicroseconds(50); //delay to ensure total duration is 150+50=200 microseconds
PORTD=0; //output back a 0
check=1; //condition to exit the loop
}
t=t+1;
}
}
For some reason, the pulse generated is not exactly what I am looking for. Is there something I am doing wrong? Or is there a better implementation for something like this? Additionally, if there is something I am missing in my question, please let me know.
I realize that the arduino does not allow me to output analog values
In order to output analog values use one of the analog outputs of the Arduino.
They are marked with a ~
Here' an example from the Arduino reference:
int ledPin = 9; // LED connected to digital pin 9
int analogPin = 3; // potentiometer connected to analog pin 3
int val = 0; // variable to store the read value
void setup() {
pinMode(ledPin, OUTPUT); // sets the pin as output
}
void loop() {
val = analogRead(analogPin); // read the input pin
analogWrite(ledPin, val / 4); // analogRead values go from 0 to 1023, analogWrite values from 0 to 255
}

Read analog input from Arduino Uno Wifi Wire/TWI/I2C pins (A4 & A5)

I recently got an Arduino Uno Wifi (flashed it with the Wifilink firmware to support UDP) and I have created a simple sketch to read analog values from a flex sensor.
I am using the code below (copy paste from the official website)
const int FLEX_PIN = A4; // Pin connected to voltage divider output
// Measure the voltage at 5V and the actual resistance of your
// 47k resistor, and enter them below:
const float VCC = 4.98; // Measured voltage of Ardunio 5V line
const float R_DIV = 47500.0; // Measured resistance of 3.3k resistor
// Upload the code, then try to adjust these values to more
// accurately calculate bend degree.
const float STRAIGHT_RESISTANCE = 37300.0; // resistance when straight
const float BEND_RESISTANCE = 90000.0; // resistance at 90 deg
void setup() {
Serial.begin(9600);
pinMode(FLEX_PIN, INPUT);
}
void loop() {
// Read the ADC, and calculate voltage and resistance from it
int flexADC = analogRead(FLEX_PIN);
float flexV = flexADC * VCC / 1023.0;
float flexR = R_DIV * (VCC / flexV - 1.0);
Serial.println("Resistance: " + String(flexR) + " ohms");
// Use the calculated resistance to estimate the sensor's
// bend angle:
float angle = map(flexR, STRAIGHT_RESISTANCE, BEND_RESISTANCE, 0, 90.0);
Serial.println("Bend: " + String(angle) + " degrees");
Serial.println();
delay(500);
}
The code does not work in the Arduino Uno Wifi: it does not show any change in the bend degrees. However, it works in another Arduino Uno I have for testing.
Also I made a test and I found out that pins 4 and 5 in Arduino Uno Wifi produce current for some reason even with an empty script, capable of lighting a LED (while pins 0,1,2,3 do not light it up).
The same applies for the values for the sensors. For example if I put the flex sensor in analog pin 0 then the values change when I bend it (e.g. 362 read not bend and 600 bend, which is fine).
On the other hand when I put the pin of the sensor in A4 or A5 there is a change from 1023 (starting value) to 982 and it won't change no matter if I bend the sensor.
I was recently informed that those pins are Wire/TWI/I2C pins. Is there any way i can read analog input from those pins?
Also posted in Arduino forums link
'WiFi' is connected to those pins.
pins A4 and A5 are Wire/TWI/I2C pins and there is the additional UART SC16IS750 connected to which the esp8266 is connected on Uno WiFi

Simple Analog Read Arduino

I am trying to program some software for my Arduino to read data from an IR fire detector module, I know the module works but I just cannot get the Arduino to read from it and carry out a function correctly. I want it to work like this...
const int IRDetector1Input = A2;
const int IRDetector1Output = A1;
const int LEDButton = 3;
void setup(){
pinMode(IRDetector1Input, INPUT);
pinMode(IRDetector1Output, OUTPUT);
pinMode(LEDButton, OUTPUT);
void loop(){ //Problem Point
if analogRead(IRDetectorInput, HIGH); //This is the problem, the code doesn't match with digital or analog write.
digitalWrite(LEDButton, HIGH);
There are a couple of issues that I see.
One, is that you are using the analogRead() function incorrectly. When you perform an analogRead() the function reads a digital representation of the voltage as seen at the requested pin and returns an integer value (0 to 1023). Also, this function only takes a single parameter, the pin number. You are sending the pin number and HIGH. Here is an example of what to do if you wanted to know what the digital representation of the voltage was at that analog pin:
int analogValue;
analogValue = analogRead(IRDetector1Input);
The second issue is with your if() statement. I believe that you are trying to see if the value received at the pin (where your IR detector is connected) is actually HIGH. First, your if() statement would be more correct (but still wrong), like this:
if (analogRead(IRDetector1Input) == HIGH)
digitalWrite(LEDButton, HIGH);
The reason that it is still wrong is that HIGH is a value that is defined as being the integer number 1, whereas LOW is defined as 0. So, you would be comparing the return value of analogRead() which could be anywhere from 0 to 1023, to the number 1.
So... how can you fix it? Well, it's tough to say without knowing how your IR detector module works. If the detector sends a digital value (a high voltage or a low voltage and not something in between) to your Arduino, use digital functions and a digital pin (i.e. digitalRead()). However, if your IR is actually sending an undetermined voltage, then set an analog threshold and check for it. You will need to run tests to determine where this threshold should be. For example:
#define ANALOG_IR_THRESHOLD 750 /* Arbitrarily set */
if (analogRead(IRDetector1Input) >= ANALOG_IR_THRESHOLD)
{
digitalWrite(LEDButton, HIGH);
}

Arduino pull-up resistor not working

I am using an Arduino board to read out the value of a soft potmeter. (a strip that detects touch). This works perfectly fine as long as the strip is being touched (a resistance is added to the current).
When the strip is not touched, a completely random floating number is read by the analog pin. Forums mention that you have to add a pullup/pulldown resistor to cancel this effect, but this does not seem te be working. What is wrong with this code?
int potPin = 2;
int curval = 0;
// detect potmeter value
void setup() {
//enable pullup resistor, but still results in erratic output
//when potmeter is not touched
digitalWrite(potPin, HIGH);
//write to serial
Serial.begin(9600);
}
void loop() {
curval = analogRead(potPin);
// this works when the potmeter is being pressed (displays 0 to 1024)
Serial.println(curval);
delay(150);
}
Change
int potPin = 2;
to
int potPin = A2;
Your original use of "2" in both places is assigning Digital Pin 2 to pull-up and reading from Analog Channel 2. As "2" maps correspondingly to is PortD bit 2 and Analog Channel 2 (aka ADC2) is PortC bit 2. As shown below
digitalWrite(2, HIGH); // Pin D2
curval = analogRead(2); // AMUX Channel 2
where A2 shown below is interpreted as follows
digitalWrite(A2, HIGH); // Pin (A2 aka D16)
curval = analogRead(A2); // AMUX Channel 2 on Pin A2
On an UNO (ATmega328) the analogRead() function will interpret 0-7 as channels and will convert the pins A0 through A7 (D14-D21) to corresponding channels, to read from.
Note:
ADC6 and 7 are not available on the chip used on the UNO.
A0-A7 are alias for Digital 14 through 21. Where the labels A0-A7 are typically used.

Speed measurement with arduino and ultrasonic hc-sr04 sensor?

i want made speed detection "device" using with Arduino and two ultrasonic hc-sr04 like this link. but I want to make it with ultrasonic instead by LDR.
from that link. how lasers and ldr work, like this
The resistors are used as pull-down resistors and I wired the sensors and put them in a case, to avoid them detecting surrounding light. For each case, a hole was drilled so that the laser beam can light the sensor while the ambient light does not affect the sensor.
The working principle is easy: an object that passes by will "cut" the laser beams, this means the LDR sensor will detect this sudden drop of light intensity. First I defined a threshold value under which the sensor is considered triggered, once the value is under threshold for the first sensor then Arduino waits for the second one to be triggered. During this waiting time it counts the elapsed time between the two events. When the second beam is interrupted, the timer stops and now is just simple math. The distance between the 2 sensors is known, the time between the two events is known, and speed can be computed as speed = distance/time.
Below the Arduino code:
/*
by Claudiu Cristian
*/
unsigned long time1;
int photocellPin_1 = 0; // 1st sensor is connected to a0
int photocellReading_1; // the analog reading from the analog port
int photocellPin_2 = 1; // 2nd sensor is connected to a1
int photocellReading_2; // the analog reading from the analog port
int threshold = 700; //value below sensors are trigerd
float Speed; // declaration of Speed variable
float timing;
unsigned long int calcTimeout = 0; // initialisation of timeout variable
void setup(void) {
// We'll send debugging information via the Serial monitor
Serial.begin(9600);
}
void loop(void) {
photocellReading_1 = analogRead(photocellPin_1); //read out values for sensor 1
photocellReading_2 = analogRead(photocellPin_2); //read out values for sensor 2
// if reading of first sensor is smaller than threshold starts time count and moves to calculation function
if (photocellReading_1 < threshold) {
time1 = millis();
startCalculation();
}
}
// calculation function
void startCalculation() {
calcTimeout = millis(); // asign time to timeout variable
//we wait for trigger of sensor 2 to start calculation - otherwise timeout
while (!(photocellReading_2 < threshold)) {
photocellReading_2 = analogRead(photocellPin_2);
if (millis() - calcTimeout > 5000) return;
}
timing = ((float) millis() - (float) time1) / 1000.0; //computes time in seconds
Speed = 0.115 / timing; //speed in m/s given a separation distance of 11.5 cm
delay(100);
Serial.print(Speed);
Serial.print("\n");
}
how to implement the code with ultrasonic HC-SR04 sensors?
the coding is problem for me. hopefully someone can help me...... :(
Please excuse my poor English !
There are already lots of examples on the internet, so if all you want to do is copy, google arduino sr04
But if you want to know how to do it...
The sr04 has 4 pins, vin, gnd, trigger, and echo.
Connect vin and ground to +5 and gnd
Connect trigger to a digital output pin
Connect echo to a digital input pin
Trigger by going low for 2 microseconds (us) and then high for 10 us then low again
Then get the results with a pulseIn from the echo pin
Read the data sheet for more information

Resources