Arduino IR controlled light fade issue - arduino

Never coded before. I'm having trouble adding a fade feature to this code. I have added a limit of 50. I want the LED to become dimmer the closer the limit. However, the light does cut off after 50 which is what I am also looking for. I am using a SHARP 2Y0A02 F 26 IR sensor to measure the distance.
I have played around with different IF loops and have had no success. When I tried the code without the limit it would fade quite well, however I need the same effect within the limit.
#define sensor A0 // Sharp IR 2Y0A02 F 26
int led = 6;
int brightness = 0;
void setup() {
Serial.begin(9600);
pinMode(led, OUTPUT);
}
void loop() {
analogWrite(led, brightness);
// 5v
float volts = analogRead(sensor) * 0.0048828125; // value from sensor * (5/1024)
int distance = 9462/(analogRead(sensor) - 16.92); // Distance in CM
int fade = distance;
delay(1000); // slow down serial port
if (distance <= 50) {
brightness = -distance;
}
else {
brightness = 0;
}
Serial.println(distance); // print the distance
}
I expect the light to be very dim at 50 and be gradually brighten when the object is getting closer to 0.

Related

Pulsein() function blocks other tasks from running silmultaneously

I am using a zumo bot with a reflectance sensor used to follow a black line. I want to use an arduino to make the zumo bot stop once it gets a certain distance from an obstacle.
I have an ultrasonic sensor (HC-SR04) which ive connected to the bot.
Both of these tasks work independently but once i merge the code together(so it follows the line aswell as stoping when it detects an object using the ultrasonic sensor), it doesn't work properly.. (the zumo bot no longer follows the line)
I THINK it is to do with the pulsein() function blocking any other tasks but not sure.
My code is below. Can anyone help please?
#include <ZumoShield.h>
ZumoBuzzer buzzer;
ZumoReflectanceSensorArray reflectanceSensors;
ZumoMotors motors;
Pushbutton button(ZUMO_BUTTON);
int lastError = 0;
// This is the maximum speed the motors will be allowed to turn.
// (400 lets the motors go at top speed; decrease to impose a speed limit)
const int MAX_SPEED = 400;
#define echoPin A4
#define trigPin A5
// defines variables
long duration; // variable for the duration of sound wave travel
int distance; // variable for the distance measurement
void setup()
{
reflectanceSensors.init();
pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
pinMode(echoPin, INPUT); // Sets the echoPin as an INPUT
// Initialize the reflectance sensors module
// Wait for the user button to be pressed and released
button.waitForButton();
// Turn on LED to indicate we are in calibration mode
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
// Wait 1 second and then begin automatic sensor calibration
// by rotating in place to sweep the sensors over the line
delay(1000);
int i;
for(i = 0; i < 80; i++)
{
if ((i > 10 && i <= 30) || (i > 50 && i <= 70))
motors.setSpeeds(-200, 200);
else
motors.setSpeeds(200, -200);
reflectanceSensors.calibrate();
// Since our counter runs to 80, the total delay will be
// 80*20 = 1600 ms.
delay(20);
}
motors.setSpeeds(0,0);
// Turn off LED to indicate we are through with calibration
digitalWrite(13, LOW);
// Wait for the user button to be pressed and released
button.waitForButton();
Serial.begin(9600); // // Serial Communication is starting with 9600 of baudrate speed
Serial.println("Ultrasonic Sensor HC-SR04 Test"); // print some text in Serial Monitor
Serial.println("with Arduino UNO R3");
}
void loop()
{
unsigned int sensors[6];
// Get the position of the line. Note that we *must* provide the "sensors"
// argument to readLine() here, even though we are not interested in the
// individual sensor readings
int position = reflectanceSensors.readLine(sensors);
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin HIGH (ACTIVE) for 10 microseconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Our "error" is how far we are away from the center of the line, which
// corresponds to position 2500.
int error = position - 2500;
// Get motor speed difference using proportional and derivative PID terms
// (the integral term is generally not very useful for line following).
// Here we are using a proportional constant of 1/4 and a derivative
// constant of 6, which should work decently for many Zumo motor choices.
int speedDifference = error / 4 + 6 * (error - lastError);
lastError = error;
// Get individual motor speeds. The sign of speedDifference
// determines if the robot turns left or right.
int m1Speed = MAX_SPEED + speedDifference;
int m2Speed = MAX_SPEED - speedDifference;
if (m1Speed < 0)
m1Speed = 0;
if (m2Speed < 0)
m2Speed = 0;
if (m1Speed > MAX_SPEED)
m1Speed = MAX_SPEED;
if (m2Speed > MAX_SPEED)
m2Speed = MAX_SPEED;
motors.setSpeeds(m1Speed, m2Speed);
//if (distance <20){
// motors.setSpeeds(0,0);
// }
////////////////////////////////////////////
// Calculating the distance
distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and back)
// Displays the distance on the Serial Monitor
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
} ```
Of course pulseIn is blocking function. Arduino project is open source, you can easily check source code
Here is C equivalent countPulseASM function which does measurement.
unsigned long pulseInSimpl(volatile uint8_t *port, uint8_t bit, uint8_t stateMask, unsigned long maxloops)
{
unsigned long width = 0;
// wait for any previous pulse to end
while ((*port & bit) == stateMask)
if (--maxloops == 0)
return 0;
// wait for the pulse to start
while ((*port & bit) != stateMask)
if (--maxloops == 0)
return 0;
// wait for the pulse to stop
while ((*port & bit) == stateMask) {
if (++width == maxloops)
return 0;
}
return width;
}
If you need measure pulse length in non blocking way, use hw counters.

Why does the ledstrip stop partway and then go all the way and can I make this more efficient

So I need some help reviewing and editing the code below. Is there a way to make it more efficient instead of what I did? Also, are there better ways to do some of the methods I did? Answers are appreciated greatly (I'm fairly new to Arduino).
The code below is for a corridor ledstrip that lights up when the distance sensor on the Arduino detects anything below a certain distancenear it (yes, I thought of using a motion sensor but I only had distance sensors on hand).
const int trigPin = 9;
const int echoPin = 10;
float duration, distance;
#include <FastLED.h>
#define LED_PIN 6
#define NUM_LEDS 60
int timingnum = 0;
//#define BRIGHTNESS bright
int bright = 100;///the brightness of the leds
int lednum = 60;///the number of leds available
int timer;
CRGB leds[NUM_LEDS];
void setup() {
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
Serial.begin(9600);
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
// FastLED.setBrightness( BRIGHTNESS );
}
void loop() {
lights();
}
void sensor() { ///THIS IS CLEAN
digitalWrite(trigPin, LOW);
delayMicroseconds(timingnum);
digitalWrite(trigPin, HIGH);
delayMicroseconds(timingnum);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration*.0343)/2;
Serial.print("Distance: ");
Serial.println(distance);
}
// in the lights the reason why it wouldnt output the data for the
// represented while loops is because the while loop continued running
// without the data from the distance and thus it needs to constantly
// be updated in the while loop conditional statments
void lights() {
sensor(); //data update
while (distance <= 10) {
for (int x = 0; x <= 60; x++) {
leds[x] = CRGB(255,255,255);
FastLED.show();
sensor(); //sensor update
}
for (timer = 0; timer <=800; timer++) {
sensor();
}
sensor(); //replaces the data updates above
}
sensor(); //sensor update
while (distance >= 11) {
for (int x = 0; x <= 60; x++) {
leds[x] = CRGB(0,0,0);
FastLED.show();
}
sensor(); //data update
}
}
I would be tempted to make a little function to set the RGB colors of your LED strip: void fillup(byte r, byte g, byte b). Then you would call it in two places: fillup(0,0,0) and fillup(127,127,127) (yeah, not 100% on).
Also, I'm confused why you have so many sensor() calls in the first while loop. Seems like you only need to call it once when you need updated values for distance.
Also, the comments on the sensor calls are confusing... after reading them I have no idea what sensor is supposed to do. I tend to put a comment before functions that describes what they do, and put a stand-alone comment in the code to explain what the next "paragraph" does. And I avoid banners - they get in the way.
Do you want FastLED.show() inside the loop that updates the colors? Or just after the loop, to update the hardware after the array is changed? IDK, just asking.
I usually do not mind globals, but in this case you would be better off letting sensor return the distance. Then you could while ( sensor() <= 10 ). Or use a do.. while loop with one call to sensor at the bottom if you want to keep the global.
I'd try to get rid of the floating point, too... just calculate what your thresholds are in the raw echo values, and use those. Do we really care what the internal units of measurement are?
Sorry for the long unload... There's nothing wrong with what you have.

Doppler Radar analogRead()

I've been doing a project on reading doppler speed and creating velocity data. I don't have a firm background on electric engineering / signal processing but I've researched quite a bit so far. Please bear with me if I get things wrong in my explanation.
I am currently using HB100 and CDM324 breakout model. The objective in this project is to get the voltage reading from the module and create a spectrogram though FFT in MATLAB. I got a sample data from BlackCatScience with the hand moving towards the Sensor at a fast speed. Its plot is shown below:
Hand Speed Using Doppler Radar
And I've assembled my arduino kit like the picture below:
Arduino-HB100_kit
Connections are:
VCC -> 5V GND -> GND FOUT -> Pin 8 VOUT -> Pin A5
So far, I found out that HB100 supports pulse/CW usage and used the code below to measure the frequency using HB100.
#include <MsTimer2.h>
#include <FreqMeasure.h>
//--------------GlOBAL VARIALBES---------------------
double raw_data = FreqMeasure.read();
double sum = 0;
int count = 0;
double raw_data_array[10];
unsigned long timeStamp = 0;
//---------------------------------------------------
void setup() {
Serial.begin(115200);
FreqMeasure.begin();
Serial.print("Time (ms)");
Serial.print("\t");
Serial.println("Hz");
}
void loop() {
timer();
freq_measure();
}
void timer() {
timeStamp+=1;
}
void freq_measure() {
while (timeStamp < 101) {
if(FreqMeasure.available()) {
//average readings
sum += FreqMeasure.read();
count ++;
if (count > 2) {
float frequency = FreqMeasure.countToFrequency(sum/count);
// Serial.print(timeStamp);
// Serial.print("\t");
Serial.println(frequency);
timeStamp++;
sum = 0;
count = 0;
}
}
}
}
The problem with this code is that, I want to measure the voltage reading at every, say for example, 1 millisec. However, this code is similar to using pulseIn function and the rate at which the data is out differs on whether I'm moving my hand to/from the sensor or not. When I'm not moving, the data output become slow, and when I'm moving, the data output rate is fast.
Hence, I decided to use some other code and use analogRead function like below:
//-----------------------------------------------------------------
#define RADAR A5 //pin number for VOUT
//--------------------GLOBAL VARIABLES-----------------------------
unsigned long timeStamp;
//-----------------------------------------------------------------
void setup() {
Serial.begin(115200);
pinMode(RADAR, INPUT);
Serial.println(F("Settings Complete" ));
}
void loop() {
// 1 millisec == 0.001 second --> 1000 millisec == 1 second
// we want about 5 seconds of data, hence the loop runs for 5000 millisec
while (timeStamp < 5000){
showReading();
}
}
void showReading() {
// timeStamp = millis();
// Serial.print(timeStamp);
// Serial.print("\t");
//Read input on analog pin 5:
int sensorData = analogRead(RADAR);
// float voltage = sensorData * (5.0 / 1023.0);
Serial.println(sensorData);
}
This time, the serial monitor is giving me a value between 0 and 1023 and that's great, but even if I move my hand in front of the sensor, the values change but minimally. What should I do to correct this and get a plot like the graph above?
Thanks for reading such a long question. Have a great day!

Beginner Arduino loop function and variable

This is the revised code, the initial value is reading ridiculously high without the conversion!! How do I get the conversion to apply to the initialTemp as well temperatureC?
The code you have helped with as far as I can tell is exactly what I was trying to achieve, but obviously.
Thanks again!!
int pin_tempRead = 0; // temperature sensor pin
int coolLED = 2; // cooling LED digital pin
int heatLED = 3; // heating LED digital pin
float initialTemp;
float cutOffTemp = 30; //cut off temperature = 30°C
void setup()
{
Serial.begin(9600); //Start the serial connection with the computer
pinMode(heatLED, OUTPUT); //initialise as OUTPUT
pinMode(coolLED, OUTPUT); //initialise as OUTPUT
initialTemp = analogRead(pin_tempRead); // read the initial temp
Serial.print("Initial temperature: "); Serial.print(initialTemp); Serial.println("C"); //prints out starting temperature
}
void loop() // run over and over again
{
//getting the voltage reading from the temperature sensor
float current_temp = analogRead(pin_tempRead);
// converting that reading to voltage
float voltage = current_temp * 5.0; voltage /= 1024.0;
float temperatureC = (voltage - 0.5) * 100 ; //converting from 10 mv per degree with 500 mV offset
//to degrees ((voltage - 500mV) times 100)
if(temperatureC > cutOffTemp) {
// temp too high -> turn on the cooling system
digitalWrite(heatLED, LOW);
digitalWrite(coolLED, HIGH);
}else if (temperatureC < initialTemp) {
// temp too low -> turn on the heating system
digitalWrite(heatLED, HIGH);
digitalWrite(coolLED, LOW);
}
Serial.print("Current pump temperature: ");
Serial.print(temperatureC); Serial.println("C");
delay(1000);
}
the loop() function executes over and over, so it's not a good place to store initial values.
What you need to do is define a global variable, initialize it inside the setup() function and then you can read it in the loop() function
Minimalist example:
int pin_tempRead = 0; // temperature sensor pin
float initial_temp; // define a global variable
void setup() {
initial_temp = analogRead(pin_tempRead); // read the initial temp
}
void loop() {
float current_temp = analogRead(pin_tempRead);
// get the temperature difference respect to the initial one
float difference = initial_temp - current_temp;
delay(1000);
}
PD: Also is a good practice to distinguish the variables defining a hardware connection (pins) from the software ones. I usually append pin_ to the variables that define connections. Otherwise is not clear if tempRead is the value of the temperature or the pin where the sensor is attached.
Also, for the turning on and off of the heater/cooling system: You are already in a loop (the loop() function is a loop) so you don't need a while loop.
And you have some problem with our logic.
As I understood, you want to heat until the higher threshold (cutOff) is reached, then cool down until the lower threshold is reached (initialTemperature).
This is called Hysteresis, but your logic was wrong, here's the corrected one:
Just do:
void loop() {
if(temperatureC > cutOffTemp) {
// temp too high -> turn on the cooling system
digitalWrite(heatLED, LOW);
digitalWrite(coolLED, HIGH);
}else if (temperatureC < initialTemp) {
// temp too low -> turn on the heating system
digitalWrite(heatLED, HIGH);
digitalWrite(coolLED, LOW);
}
Serial.print("Current pump temperature: ");
Serial.print(temperatureC); Serial.println("C");
delay(1000);
}
By the way, you are using the initialTemperature as the low threshold for turning on the heating.
Is that what you really want?
What if the initial temperature is higher that the cutOffTemp? You will have problems in that case since the lower threshold is higher than the higher threshold.

Arduino code not working

My plan is to make an adjustable speed strobe. I'm just learning to code and this is what I have so far.
int potentiometer_pin = A0;
int led_pin = 7;
int on_time = 100;
int analog_value_multiplier = 15;
int strobe_delay = 0;
int minimum_delay = 500;
void setup() {
pinMode(led_pin, OUTPUT);
}
void loop() {
strobe_delay = minimum_delay + analogRead(potentiometer_pin) * analog_value_multiplier;
digitalWrite(led_pin, HIGH);
delayMicroseconds(on_time);
digitalWrite(led_pin, LOW);
delayMicroseconds(strobe_delay - on_time);
}
I have the LED + on digital 7 with a 220ohm resistor and the pot on analog 0, it is a 10K pot with one side hooked up to 5v+ and the other to ground. My problem is that the LED stays on and turning the pot just changes the brightness. Any help on what to do - not just a new code but what to do? I want to actually learn how to fix this.
like david said, but I will add I think you want delay not delayMicroseconds.
http://arduino.cc/en/Reference/delay
Your speeds are all WAY too fast. Multiply all your delays by about 100. You've made a pulse width modulator.

Resources