I am having problems with a hard code example of accelerating a stepper motor. I can have the motor run at a constant speed but in order for it to start and not lose steps, I need an acceleration as it will move something relatively heavy. The code I have written does not seem to want to iterate the way it does without the additional code. The code is copied below in the void loop() section of the arduino code.
`digitalWrite(dir, HIGH);
for(int i=0; i <= distance; i++){
Serial.println(i);
if(i<1000){
wait = 500 - (0.45*i);
}
else{
wait = 50;
}
digitalWrite(pul, HIGH);
delayMicroseconds(wait);
digitalWrite(pul, LOW);
delayMicroseconds(wait);
}`
The program does not want to operate as written. The AccelStepper library is not a great option and this type of acceleration shouldn't be hard to add. I don't understand why this isn't working.
I have added continue; after the if and else statements as well and that does not fix my problem.
Also for decceleration my plan was to do the same in the opposite direction.
The SpeedyStepper Library (https://github.com/Stan-Reifel/SpeedyStepper)is a good option for you. I've been used for years, it has several options for controlling stepper motors, including acceleration and speed.
Related
The arduino should be reading different values as the signal is a sine wave. Tried using different signal frequency as well as different delay(), still shows a constant value. Any help is highly appreciated! Thanks!!
You are printing the value of A2 while you should be reading the pin itself.
Look for analogRead() to start with and if you intend to use much higher frequencies and perhaps need more precise information then consider using an interrupt.
You are not sending the actual reading of analog input. Your code should be something like
void loop(){
int adcRead = analogRead(A2);
Serial.println(adcRead);
delay(2);
}
I have a series of relays I'm controlling with an arduino connected to solenoid valves which in turn control the flow of water around a system of pipes. The relays are to be switched at regular intervals along the lines of this:
Relay 1 and 3 high
Wait 13s
Relay 2 and 4 high
Wait 17s
Relay 1 and 3 low
Wait 13s
Relay 2 and 4 low
Wait 300s
Repeat
I started with a simple series of delays commands like this:
#include <DmxMaster.h>
void setup() {
DmxMaster.maxChannel(8);
}
void loop() {
delay(300000);
DmxMaster.write(1,HIGH);
DmxMaster.write(7,HIGH);
delay(13000);
DmxMaster.write(2,HIGH);
DmxMaster.write(8,HIGH);
delay(17000);
DmxMaster.write(1,LOW);
DmxMaster.write(7,LOW);
delay(13000);
DmxMaster.write(2,LOW);
DmxMaster.write(8,LOW);
}
Most of the time this works, but I will see instances where it'll skip one or more delay lines and jump to the next step. I started to look at the millis function for the longest delay (300s) and came up with the following, but I'm wondering how to implement this for the shorter delays and if this would be of any improvement:
#include <DmxMaster.h>
unsigned long currentTime;
unsigned long loopTime;
void setup()
{
DmxMaster.maxChannel(8);
currentTime = millis();
loopTime = currentTime;
}
void loop()
{
currentTime=millis();
if(currentTime >= (loopTime + 300000)){
DmxMaster.write(1,HIGH);
DmxMaster.write(7,HIGH);
delay(13000);
DmxMaster.write(2,HIGH);
DmxMaster.write(8,HIGH);
delay(17000);
DmxMaster.write(1,LOW);
DmxMaster.write(7,LOW);
delay(13000);
DmxMaster.write(2,LOW);
DmxMaster.write(8,LOW);
loopTime = currentTime;
}
}
Thanks in advance,
Cameron
In my own project, I have the same kind of constraints: I need to check sensors, get the data, analyze them and choose what to do at different intervals.
The best solution I've found is ChibiOS/RT. It's a Real Time Operating System (RTOS) developed by Giovanni Di Sirio from STMicroelectronics.
It has been ported on Arduino by Bill Greiman and is available on Github : ChibiOS-Arduino.
It is very easy to use, very well documented and has a low memory and size footprint.
I'm using it in a robotic project, Moti, you can take a look if you want but Bill has a lot of great examples.
It might look like overkill at first, but once you get used to it, you'll wonder why you did not use it earlier and every Arduino project you'll be working on will have a new dimension.
Hope this helps :)
We are simulating an oven. The potentiometer sets the desired temp and the sensor reads the current temperature of a little copper plate that is "the oven."
Both the temp sensor are connected to their own analog input pin on my arduino uno. Individually, I have gotten values for both the potentiometer and the temp sensor that make sense (I am monitoring the values on the serial window). However, when I adjust the potentiometer it significantly alters the sensor reading.
For example:
The potentiometer is at its 0 position, and the sensor is in the room temperature air. The serial shows TempSensor = 22 C, TSet = 0 C. This is normal.
Then when I turn the pot up: TempSensor= 40 C, TSet=55 C. -But the temperature sensor is still in the room temp air! So the pot value, TSet, goes up like it should, but also affects the sensor reading even though the temperature hasn't really changed.
Any advice would be greatly appreciated. Thanks!
void setup() {
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(A3);
float tsens = map(sensorValue, 0, 1023, 0, 500);
int sensorValue2 = analogRead(A1);
float tset = map(sensorValue2, 0, 1023, 0, 70);
Serial.println(tsens);
Serial.println(tset);
}
I've recently bumped into a similar problem and my searches suggest that inserting a delay between the reads can help. On this question, I found this answer and this answer particularly helpful.
The idea is that you need to let some time pass after making a reading, then make another reading after the ADC has stabilized. Here's a function I have been using:
int safeAnalogRead(int pin)
{
int x = analogRead(pin); // make an initial reading to set up the ADC
delay(10); // let the ADC stabilize
x = analogRead(pin); // toss the first reading and take one we will keep
delay(10); // delay again to be friendly to future readings
return x;
}
I'm still having trouble getting an accurate reading of several potentiometers connected to the analog pins configured as a voltage dividers between vcc and ground, but at least now the values are stable.
BTW, it could be argued that since you have a delay after the first reading, it isn't necessary to have the second delay. This might matter if you call safeAnalogRead() twice in quick succession on two different pins.
You most likely have a ungrounded or miswired grounding on your temperature sensor. The pin configurations on the analog pins in Arduinos are layed out very close to each other such that floating voltages will move up or down when nearby pins have an applied voltage. If your ground connection (or power, though if it's correct at the beginning it's probably ground) for the sensor is disconnected or fixed to a high impedance line the analog voltages will move all over the place as other normally minuscule voltage sources will dominate the signal pathing. It probably fluctuates heavily if you put your finger near the A3 pin as well.
Is it noise or a bad value? I did a little test routine that looks at a pin and checks it against previous max and min values. I printed it to the serial monitor whenever a new boundary value showed up. If the wrong value is stable, check the circuit. If its noisey around a valid value, a digital low pass filter works pretty well. Take 34 readings of the pot. Find the highest and lowest values and discard those. Then take the average of the remaining 32 readings. I saw a 90% improvement in my setup (40 count error down to 3). 36 readings with 2 high and 2 low discarded would probably improve things further. If you have the time, you can do a double pass filter. Do this same process 34 times, then throw away the high and low and average it again. All together this is 34 x 34 readings, so noise should go away, but you are taking a long time to get a sample and a pot change will take awhile to get detected. To help with the time, I read the pot every pass through the main loop and save each value in a circular buffer. When I need to read a pot, I look at the historical 33 readings along with a 34th new one.
I have run into this issue before when reading multiple analog sensors in rapid succession. One possible cause(and the one I experienced) is the fact that the arduino only has 1 ADC and it charges a capacitor to take that reading. That capacitor can remain charged between readings thus skewing them.
Introducing a delay could potentially help with this as another user has pointed out, however the cleanest solution I was able to come up with was to "Reset" and discharge the ADC capacitor by taking an analog read of a third pin that is connected directly to ground.
int sensorValue;
int sensorValue2;
float tsens;
float tset;
int resetADC;
void setup()
{
Serial.begin(9600);
pinMode(A0,input);
pinMode(A1,input);
pinMode(A3,input);
}
void loop()
{
resetADC = analogRead(A0);
sensorValue = analogRead(A3);
tsens = map(sensorValue, 0, 1023, 0, 500);
resetADC = analogRead(A0);
sensorValue2 = analogRead(A1);
tset = map(sensorValue2, 0, 1023, 0, 70);
Serial.println(tsens);
Serial.println(tset);
}
I'm new to microcontrollers and I need help reading voltages and printing them in the serial monitor. I have done this using a potentiometer, but I was wondering if I could do the same with just voltages. Below is the code that I used when I read the potentiometer values:
I have tried reading voltages but when I input a voltage smaller than between 3-5V in pin A0 I get 0s in the serial monitor
int potPin = 0; // select the input pin
int val = 0; // variable to store the value coming from the function generator
void setup()
{
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
val = analogRead(potPin); // read the value from the function generator
Serial.println(val);
delay(1000); //Sampling rate for the signal
}
as Udo Klein said, this looks like a hardware issue. try setting up your circuit like this: http://imgur.com/PYbeqLq
note that the grounds are shared between the function generator and the arduino - this is important for ensuring that voltages are measured correctly. remember that voltage is actually a difference in electric potential, so you need a common reference point to measure from.
To answer your question, yes you can read voltages from another piece of hardware.
As gearbot tells you it is important to keep a common ground between the arduino and the other piece of hardware.
Also be carefull, the arduino can only measure voltages between 0 and 5 Volts. Don't try to measure higher voltages without adjusting the circuitry as you might destroy your arduino board.
If you're unsure measure the voltages before attaching to the arduino with a multimeter.
The Uno has 6 analog inputs, labeled A0 through A5, each of which provide 10 bits of resolution (i.e. 1024 different values). By default they measure from ground to 5 volts, though is it possible to change the upper end of their range using the AREF pin and the analogReference() function.
edit:
I didn't see the added comment at the bottom of your post. This indicates indeed a hardware problem (probably in your circuitry)
To be sure the arduino does the right thing, measure the voltage with your multimeter between pin A0 and GND while your hardware is attached and working. You should be able to read the correct voltage there.
I suspect it will give the same values as the Arduino.
Then trace back your circuitry with your multimeter (keeping GND attached) to find where something is going wrong.
Try scaling your 0 to 5 or 1-5v input
using map function.
int setValue = map(ana1Value, 0, 1023, 0, 100);
could be a help for you.
the analogue input voltage is the scaled 0-100 then you can work with that
I've just hooked up a electret microphone to an Arduino, and I'd like to sample between the ranges of 1 kHz and 4 kHz.
I understand this is limited to the machine code and the ADC, so I'm trying to keep the sketch simple.
Is it possible to sample between these frequencies with the sketch below?
const int analogPin = 0;
int ledPin = 13;
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
int mn = 1024;
int mx = 0;
for (int i = 0; i < 5; ++i) {
int val = analogRead(analogPin);
mn = min(mn, val);
mx = max(mx, val);
}
if (mx-mn >= 50) {
digitalWrite(ledPin, HIGH);
}
else {
digitalWrite(ledPin, LOW);
}
}
Arduino is a prototyping platform consisting of a number of hardware boards plus a software abstraction layer. For a question like this, it is useful to consider the capabilities of the underlying hardware, as these provide the ultimate limits. I'll assume you are using Arduino Uno/Nano, the story is different for Due.
According to the datasheet, each ADC reading (beyond the first one) takes 13 ADC clock cycles. ADC clock (different from the MCU) clock is derived by dividing the system clock by some factor, at least 2. So at 16Mhz board this amounts to 0.6 million samples per second. So far so good. However, that's not the end of the story, you still need to read the data. If you use interrupts, even if you do something very simple, experience suggests that you will lose about 100 clock to interrupt processing. Now you are down to 126K samples/second. But this is a theoretical maximum.
The datasheet states that for maximum accuracy for the ADC requires 50kHz - 200kHz ADC clock. In the Arduino code (in wiring.c), a division factor of 128 is chosen:
sbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
This means that each conversion takes 128*13 = 1764 clocks, which yields a theoretical maximum of 10K samples per second. It is a little bit worse than that given that the readAnalog() function does something beyond just starting the ADC conversion and waiting for it to finish, but it shouldn't be too much worse. This doesn't involve your code of course: any processing you do on the results of readAnalog() will make it more difficult to capture more samples. But yes, to capture at 4Khz you will need to make sure that you code spends less than 1.5k clock cycles/sample, which should be doable. Note that if you are doing five readings like you are doing in the code you posted, the maximum capture rate will be 2kHz if your code does very little.
As far as how to capture the data, you need to make deal with the fact that microphones without amplification will not give you 0-5V readings that you might expect if you are using analogRead(). In fact, microphone output voltages swing from positive to negative, however, the negative voltages will not be picked up by the ADC, and show up as just zeros, unless you give your microphone a voltage offset.
I am not exactly sure what your code that compares minimum amplitude to maximum amplitude is supposed to be doing. Are you wanting to digitize the audio? In this case you need to save all the amplitude readings collected from analogRead(), and then you can run FFTs on them on another computer: Arduino is most likely not going to be fast enough to do frequency analysis on the data.
I have heard, or rather remember reading, that the ADC could handle up to 10k-samples per second, so it should be OK up to 5 kHz. However, I have not tried this nor do I have a link to back it up at the moment.
Just try and see.
Now I know some of the Arduino library functions are slow, notably the DigitalRead/Write that has overhead of hundreds of cycles. Most of this is the sanity checking that allows people to just perform DigitalRead/Write without thinking much about setting everything up.
However, to squeeze out the maximum performance you could look into writing your own AnalogRead that is optimized for your use case.
At least some links on the subject:
Pin I/O performance (JeeLabs)
C++ Template method for faster access (JeeLabs)
I happen to have just tried this using an Arduino Uno and similar code to yours and I've been able to sample an average of 8000 times a second. That is the Nyquist frequency for 4 kHz so you're good but not much margin for error.