I wrote a sample code to measure the brightness of LED by controlling the duty cycle of LED connected to Arduino. I want to get the range of least bright light to max bright light for a specific period of period. When i put desired_brightness = 1, the LED is emitting light at 93 lux units, its not the least brightlight. Any suggestion on how to get the least bright light?
int led = 3; // the pin that the LED is attached to
int brightness =0; // how bright the LED is
int incrementfactor = 10; // how many points to fade the LED by
int desired_brightness = 255 ;
int extra_delay = 1000;
void setup() { // declare pin 9 to be an output:
pinMode(led, OUTPUT);
analogWrite(led, desired_brightness);
}
void loop() {
analogWrite(led, desired_brightness);
brightness=brightness+incrementfactor;
if (brightness==desired_brightness) {
delay(extra_delay);
}
}
I've tailored your code a bit. The main problem was you were going to maximum brightness right away, and were never decreasing it. analogWrite() only takes values from 0 to 255. You were starting at 255 and increasing from there, so it just stayed bright. Try this instead, it's the "breathing effect" you see on so many electronics these days, and loops forever:
int ledPin = 3; // the pin that the LED is attached to
int brightness =0; // how bright the LED is
int extra_delay = 1000; // the extra delay at max
int super_delay = 5000; // super delay at min
int direction = 1; // the dimmer-brighter direction
void setup() {
pinMode(ledPin, OUTPUT);
analogWrite(ledPin, 0);
}
void loop() {
analogWrite(ledPin, brightness); // light at certain brightness
//delay(5); // wait a bit, stay at this level so we can see the effect!
delay(50); // longer delay means much slower change from bright to dim
if (direction == 1) // determine whether to go brighter or dimmer
brightness += 1;
else
brightness -= 1;
if (brightness == 255) // switch direction for next time
{
direction = -1;
delay(extra_delay); // extra delay at maximum brightness
}
if (brightness == 0) // switch direction, go brighter next time
{
direction = 1;
delay(super_delay); // super long delay at minimum brightness
}
}
This will go brighter, then dim, and repeat. The delay is very important -- you can reduce it or lengthen it, but without it, the change happens so fast you can't see it by eye, only on an oscilloscope. Hope this helps you!
EDIT:
Added a "super delay" at minimum brightness for measurement of that level.
One thing to keep in mind is that pulse-width modulation like this still gives full driving voltage from the output pin. PWM just alters the ratio of the time the pin is high vs. low. On this Aduino, it's still a voltage swinging instantly and quite rapidly between 0V and 3.3V. To get a true analog voltage from this output, one needs some circuitry to filter the highs and lows of PWM into a smoother average DC voltage. If you want to pursue that, search for "RC low-pass filter" or visit a site like this one.
Related
So I have an Arduino that is reading the rpm from my car. I also have a 15-pixel neopixel strip connected to the Arduino.
What I want the Arduino to do is to make the led strip show the rpm. As the rpm increases, the number of LEDs that turn on is increased from the left side of the strip.
What I am stuck on and would love help with is that I don’t just want the LEDs to turn on or off based of the rpm, but also change brightness.
For example let’s say the rpm is at 2000, so pixel 4 (arbitrary number that will be calculated by the equation) is the top pixel to turn on. Now as the rpm is increased, pixel 5 will increase in brightness from 0 to 255. Then pixel 6 will increase in brightness and so on, creating a smooth transition between pixels.
So what I want help with is being able to input the rpm and output the top pixel and it’s brightness. From there I will be able to just fill in the LEDs below the top pixel.
I want the top rpm to be 8000.
Let me know if you need more info. Thanks!
Does this code help? This has the code to calculate the last pixel - and the brightness of that pixel.
#define NUM_LEDS 15
#define NUM_BRIGHTNESS_LEVELS 256
#define MAX_REVS 8000
void setup()
{
Serial.begin(9600);
}
void loop()
{
for ( int revs = 0 ; revs <= MAX_REVS ; revs += 500 )
{
int totalBrightness = ((float)revs / MAX_REVS) * (NUM_LEDS * NUM_BRIGHTNESS_LEVELS);
int lastPixel = (totalBrightness / NUM_BRIGHTNESS_LEVELS);
int brightness = totalBrightness % NUM_BRIGHTNESS_LEVELS;
if ( lastPixel >= NUM_LEDS )
{
lastPixel = NUM_LEDS - 1;
brightness = NUM_BRIGHTNESS_LEVELS - 1;
}
Serial.print("revs = ");
Serial.print(revs);
Serial.print(", pixel = ");
Serial.print(lastPixel);
Serial.print(", brightness = ");
Serial.println(brightness);
delay(100);
}
delay(2000);
}
I have NRG #40 wind speed sensor the output frequency is linear with wind speed
output signal range from 0 Hz to 125 Hz
0 Hz mean =0.35 m/s and 125 Hz =96 m/s and transfer function is
m/s = (Hz x 0.765) + 0.35
How can I interface this sensor with a Arduino mega
previously I connect Adafruit (product ID: 1733) which is output voltage not frequency is linear with wind speed
and this code for Adafruit :
//Setup Variables
const int sensorPin = A0; //Defines the pin that the anemometer output is connected to
int sensorValue = 0; //Variable stores the value direct from the analog pin
float sensorVoltage = 0; //Variable that stores the voltage (in Volts) from the anemometer being sent to the analog pin
float windSpeed = 0; // Wind speed in meters per second (m/s)
float voltageConversionConstant = .004882814; //This constant maps the value provided from the analog read function, which ranges from 0 to 1023, to actual voltage, which ranges from 0V to 5V
int sensorDelay = 1000; //Delay between sensor readings, measured in milliseconds (ms)
//Anemometer Technical Variables
//The following variables correspond to the anemometer sold by Adafruit, but could be modified to fit other anemometers.
float voltageMin = .4; // Mininum output voltage from anemometer in mV.
float windSpeedMin = 0; // Wind speed in meters/sec corresponding to minimum voltage
float voltageMax = 2.0; // Maximum output voltage from anemometer in mV.
float windSpeedMax = 32; // Wind speed in meters/sec corresponding to maximum voltage
void setup()
{
Serial.begin(9600); //Start the serial connection
}
void loop()
{
sensorValue = analogRead(sensorPin); //Get a value between 0 and 1023 from the analog pin connected to the anemometer
sensorVoltage = sensorValue * voltageConversionConstant; //Convert sensor value to actual voltage
//Convert voltage value to wind speed using range of max and min voltages and wind speed for the anemometer
if (sensorVoltage <= voltageMin){
windSpeed = 0; //Check if voltage is below minimum value. If so, set wind speed to zero.
}else {
windSpeed = (sensorVoltage - voltageMin)*windSpeedMax/(voltageMax - voltageMin); //For voltages above minimum value, use the linear relationship to calculate wind speed.
}
//Print voltage and windspeed to serial
Serial.print("Voltage: ");
Serial.print(sensorVoltage);
Serial.print("\t");
Serial.print("Wind speed: ");
Serial.println(windSpeed);
delay(sensorDelay);
}
Asuming you use a Arduino UNO or Nano, a easy way is to connect the sensor to pin D2 or D3, witch can be used as Interrupt pins.
You then make a function, or a ISR, that gets called every time the sensor pulses. Then you attach the newly created function to the Interrupt pin.
So it will look something like this.
byte sensorPin = 2;
double pulses = 0;
double wSpeed = 0;
long updateTimer = 0;
int updateDuration = 3000;
void setup() {
Serial.begin(115200);
pinMode(sensorPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(sensorPin), sensorISR, FALLING);
}
void loop() {
long now = millis();
if(updateTimer < now) {
updateTimer = now + updateDuration;
wSpeed = ((pulses/(updateDuration/1000)) * 0.765) + 0.35;
pulses = 0;
Serial.println("Windspeed is:" + String(wSpeed));
}
}
void sensorISR() {
pulses++;
}
The ISR functions only job is to increment the pulses variable for every pulse. Then every second you can calculate the frequency and speed. If you wait 3 second instead, like above, you will have a better resolution but will have to account for the extra time in the equation.
I have not testet this code.
The code is supposed to fade and copy the window's image to a buffer f, then draw f back onto the window but translated, rotated, and scaled. I am trying to create an effect like a feedback loop when you point a camera plugged into a TV at the TV.
I have tried everything I can think of, logged every variable I could think of, and still it just seems like image(f,0,0) is doing something wrong or unexpected.
What am I missing?
Pic of double image mirror about x-axis:
PGraphics f;
int rect_size;
int midX;
int midY;
void setup(){
size(1000, 1000, P2D);
f = createGraphics(width, height, P2D);
midX = width/2;
midY = height/2;
rect_size = 300;
imageMode(CENTER);
rectMode(CENTER);
smooth();
background(0,0,0);
fill(0,0);
stroke(255,255);
}
void draw(){
fade_and_copy_pixels(f); //fades window pixels and then copies pixels to f
background(0,0,0);//without this the corners dont get repainted.
//transform display window (instead of f)
pushMatrix();
float scaling = 0.90; // x>1 makes image bigger
float rot = 5; //angle in degrees
translate(midX,midY); //makes it so rotations are always around the center
rotate(radians(rot));
scale(scaling);
imageMode(CENTER);
image(f,0,0); //weird double image must have something not working around here
popMatrix();//returns window matrix to normal
int x = mouseX;
int y = mouseY;
rectMode(CENTER);
rect(x,y,rect_size,rect_size);
}
//fades window pixels and then copies pixels to f
void fade_and_copy_pixels(PGraphics f){
loadPixels(); //load windows pixels. dont need because I am only reading pixels?
f.loadPixels(); //loads feedback loops pixels
// Loop through every pixel in window
//it is faster to grab data from pixels[] array, so dont use get and set, use this
for (int i = 0; i < pixels.length; i++) {
//////////////FADE PIXELS in window and COPY to f:///////////////
color p = pixels[i];
//get color values, mask then shift
int r = (p & 0x00FF0000) >> 16;
int g = (p & 0x0000FF00) >> 8;
int b = p & 0x000000FF; //no need for shifting
// reduce value for each color proportional
// between fade_amount between 0-1 for 0 being totallty transparent, and 1 totally none
// min is 0.0039 (when using floor function and 255 as molorModes for colors)
float fade_percent= 0.005; //0.05 = 5%
int r_new = floor(float(r) - (float(r) * fade_percent));
int g_new = floor(float(g) - (float(g) * fade_percent));
int b_new = floor(float(b) - (float(b) * fade_percent));
//maybe later rewrite in a way to save what the difference is and round it differently, like maybe faster at first and slow later,
//round doesn't work because it never first subtracts one to get the ball rolling
//floor has a minimum of always subtracting 1 from each value each time. cant just subtract 1 ever n loops
//keep a list of all the pixel as floats? too much memory?
//ill stick with floor for now
// the lowest percent that will make a difference with floor is 0.0039?... because thats slightly more than 1/255
//shift back and or together
p = 0xFF000000 | (r_new << 16) | (g_new << 8) | b_new; // or-ing all the new hex together back into AARRGGBB
f.pixels[i] = p;
////////pixels now copied
}
f.updatePixels();
}
This is a weird one. But let's start with a simpler MCVE that isolates the problem:
PGraphics f;
void setup() {
size(500, 500, P2D);
f = createGraphics(width, height, P2D);
}
void draw() {
background(0);
rect(mouseX, mouseY, 100, 100);
copyPixels(f);
image(f, 0, 0);
}
void copyPixels(PGraphics f) {
loadPixels();
f.loadPixels();
for (int i = 0; i < pixels.length; i++) {
color p = pixels[i];
f.pixels[i] = p;
}
f.updatePixels();
}
This code exhibits the same problem as your code, without any of the extra logic. I would expect this code to show a rectangle wherever the mouse is, but instead it shows a rectangle at a position reflected over the X axis. If the mouse is on the top of the window, the rectangle is at the bottom of the window, and vice-versa.
I think this is caused by the P2D renderer being OpenGL, which has an inversed Y axis (0 is at the bottom instead of the top). So it seems like when you copy the pixels over, it's going from screen space to OpenGL space... or something. That definitely seems buggy though.
For now, there are two things that seem to fix the problem. First, you could just use the default renderer instead of P2D. That seems to fix the problem.
Or you could get rid of the for loop inside the copyPixels() function and just do f.pixels = pixels; for now. That also seems to fix the problem, but again it feels pretty buggy.
If somebody else (paging George) doesn't come along with a better explanation by tomorrow, I'd file a bug on Processing's GitHub. (I can do that for you if you want.)
Edit: I've filed an issue here, so hopefully we'll hear back from a developer in the next few days.
Edit Two: Looks like a fix has been implemented and should be available in the next release of Processing. If you need it now, you can always build Processing from source.
An easier one, and works like a charm:
add f.beginDraw(); before and f.endDraw(); after using f:
loadPixels(); //load windows pixels. dont need because I am only reading pixels?
f.loadPixels(); //loads feedback loops pixels
// Loop through every pixel in window
//it is faster to grab data from pixels[] array, so dont use get and set, use this
f.beginDraw();
and
f.updatePixels();
f.endDraw();
Processing must know when it's drawing in a buffer and when not.
In this image you can see that works
I'm building a quad-copter using an accelerometer and gyro. The form looks like this one:
My pitch is controlled by the front and back motors.
My roll is controlled by the left and right motors.
I used PID and servo libraries.
Here's my pitch stability code:
double Kp=3.15, Ki=4.3, Kd=0.6;
int throttle = 1000;
PID PitchPID(&PitchInput, &PitchOutput, &PitchSetpoint, Kp, Ki, Kd, DIRECT);
PitchPID.SetMode(AUTOMATIC);
backESC.attach(3);
frontESC.attach(5);
// arme the motors
backESC.writeMicroseconds(2000);
frontESC.writeMicroseconds(2000);
delay(5000);
backESC.writeMicroseconds(700);
frontESC.writeMicroseconds(700);
delay(2000);
void loop{
// i have the angle and pitch
int xAngle = GetX();
int Pitch = GetPitch();
PitchInput = (Pitch) ;
PitchSetpoint = 0;
PitchPID.SetOutputLimits(-150,150);
PitchPID.Compute();
backPower = PitchOutput;
frontPower = (PitchOutput*-1);
frontESC.writeMicroseconds(backPower + throttle);
backESC.writeMicroseconds(frontPower + throttle);
}
As you can see, I don't yet have a real algorithm to stabilize the quad.
I would be grateful for some help. I have already tried some samples. It didn't go well. Even help without using my PID library would be appreciated.
Scenario:
I m experimenting the thermocouple amplifier (SN-6675) with Arduino DUE.
After i'm included MAX6675 library, Arduino can measured room temperature.
However, Temp measured from arduino have 2 issues,
1) offset compare to "Fluke thermometer"
2) have tons of noise, and keep fluctuated after taking average of each 5 temperature sample.
eg, Fluke thermometer got 28.9C at room temp, arduino got 19.75~45.75C
Question: Any method/filter to reduce the measured noise, and gives a steady output?
Codes is attached for reference.
#include <MAX6675.h>
//TCamp Int
int CS = 7; // CS pin on MAX6675
int SO = 8; // SO pin of MAX6675
int SCKpin = 6; // SCK pin of MAX6675
int units = 1; // Units to readout temp (0 = ˚F, 1 = ˚C)
float error = 0.0; // Temperature compensation error
float tmp = 0.0; // Temperature output variable
//checking
int no = 0;
MAX6675 temp0(CS,SO,SCKpin,units,error); // Initialize the MAX6675 Library for our chip
void setup() {
Serial.begin(9600); // initialize serial communications at 9600 bps:
}
void loop() {
no= no + 1;
tmp = temp0.read_temp(5); // Read the temp 5 times and return the average value to the var
Serial.print(tmp);
Serial.print("\t");
Serial.println(no);
delay(1000);
}
Any method/filter to reduce the measured noise, and gives a steady output?
The Kalman filter is pretty much the standard method for this:
Kalman filtering, also known as linear quadratic estimation (LQE), is an algorithm that uses a series of measurements observed over time, containing noise (random variations) and other inaccuracies, and produces estimates of unknown variables that tend to be more precise than those based on a single measurement alone.
If your background isn't maths, don't be put off by the formulas that you come across. In the single-variable case like yours, the filter is remarkably easy to implement, and I am sure googling will find a few implementations.
The filter will give you an estimate of the temperature as well an estimate of the variance of the temperature (the latter gives you an idea about how confident the filter is about its current estimate).
You may want to go for a simpler averaging algorithm. This is not as elegant as a low pass algorithm but may be adequate for your case. These algorithms are plentiful on the web.
You can monkey around with the number of samples you take to balance the compromise between latency and stability. You may want to start with 10 samples and work from there.