Okey this is, for me , bit tricky even to ask the question:
firstly, I am using arduino to blink the led…
it blinks LED in certain pattern so there has to delay between certain patterns of blink in the program…
no problem…
okey…now i thought of adding a small tweak …
add another led and control the brightness according to the ADC value obtained on on of the pins…
okey…I did implement this…but what i noticed is …the led controlled by ADC input too some time to respond…which of course is because of the delay…
Hey people how can i solve this…read the ADC instantly…and also blink the led
I thought about using interrupts…but just a thought…any other clever solutions ???
How about posting the code so we can see what you’ve done.
please see below …this was a bit not that good post
Mee_n_Mac:
How about posting the code so we can see what you’ve done.
[quote="Mee_n_Mac"]How about posting the code so we can see what you've done.[/quote]
#include<math.h>
double t;
double brightness;
int heartpin=11;
double periodOne=277; // look at the sine wave of the heart, two cycles + one big cycle + two small cycle + bit flat part= eaual to 1667[µs]. so one small cycle is eaual to
// so 1667/3 = 555 for each small big and small. and 555/2 for each 2 small cycles.
//so period = 277 [µs]
double periodTwo=555;
double periodThree=277;
double ampOne=10;
double ampTwo=150;
double ampThree=10;
int count=0;
byte keyboard;
int ontime, offtime;
int potRead;
void setup()
{
pinMode(heartpin,OUTPUT);
Serial.begin(9600);
pinMode(A0, INPUT);
pinMode(10,OUTPUT);
}
void loop()
{
ontime=131; offtime=425 ;
for(t=0;t<555;t++)
{
brightness=ampOne*sin(2*3.1417*(1/periodOne)*t);
if(brightness<0) brightness=-1*brightness;
analogWrite(heartpin,brightness);
// Serial.println("first block:");
// Serial.println(brightness);
delayMicroseconds(ontime);
}
for(t=0;t<555;t++)
{
brightness=ampTwo*sin(2*3.1417*(1/periodTwo)*t);
if(brightness<0) brightness=-1*brightness;
analogWrite(heartpin,brightness);
// Serial.println("second block:");
// Serial.println(brightness);
delayMicroseconds(ontime );
}
for(t=0;t<555;t++)
{
brightness=ampOne*sin(2*3.1417*(1/periodOne)*t);
if(brightness<0) brightness=-1*brightness;
analogWrite(heartpin,brightness);
// Serial.println("third block:");
// Serial.println(brightness);
delayMicroseconds(ontime);
}
analogWrite(heartpin,10);
delay(offtime);
{
// I would like this to be instantaneous
// potRead=analogRead(A0);
// analogWrite(10,potRead*0.2490234375);
}
}
I’ve setup a state machine that I think does what you intended to do. Along the way I corrected a couple of things (constants as variables, the t < 555 in every case) as well. The code initializes to state = 1 and effectively runs the 1’st for loop you had. When t = periodOne (not 555), the state becomes 2 and effectively runs the 2’nd for loop you had. When t (which was reset) = periodTwo (which = 555) state goes to 3 and then run’s the 3’rd for loop you had. It does this for periodThree, which is 277, same as periodOne but not = 555, which you had in your code. State = 4 lasts just one main loop but implements the time delay and amplitude = 10 that your old code had. The way to think about it is the new code does in the main loop() what you used to do in your old for loops and adds in the analogRead and Write you wanted. The amplitude and period are changed from state to state so the analogWrite to the “heart pin” does what your code did.
Given the new coding the time to run the main loop() will not equal the time needed to run the old for loops. You had a delay of 131 usecs (give or take) before the next iteration of the for loop calculations. An analogRead() is some 100+ usecs all by itself. Thus you may or may not want to retune the value for “ontime”. That is the new value for “ontime” might need to be (131 - 100+) usecs. I don’t know how you arrived at that value, given the differing periods you have and how you do the calculations (using periodOne, Two, etc). Also be aware the analogWrite() outputs a PWM waveform, and that it takes some time to clock out all the bits to complete one PWM cycle. Re-doing an analogWrite() too quickly after the prior Write() won’t get you what I think you want. (see next comment)
It’s not clear to me that your old code did what I am guessing you wanted it to, and my new code is no different in this respect. So if the old code was wrong, the new will be wrong as well. In any case have a look at it and see if it incorporates the “immediate” analogRead and analogWrite you wanted to add while retaining the old functionality … though done in a different way. Ask questions after you’ve read it through.
#include<math.h>
double t;
double brightness;
const int heartpin=11;
// look at the sine wave of the heart, two cycles + one big cycle + two small cycle
// + bit flat part= equal to 1667[µs]
// so one small cycle is equal to
// so 1667/3 = 555 for each small big and small. and 555/2 for each 2 small cycles.
// so period = 277 [µs]
const double periodOne=277;
const double periodTwo=555;
const double periodThree=277;
double period = periodOne;
const double ampOne=10;
const double ampTwo=150;
const double ampThree=10;
double amp = ampOne;
byte keyboard;
int ontime = 131;
int offtime = 425;
int d_time = ontime;
byte state = 1;
int potRead;
void setup()
{
pinMode(heartpin,OUTPUT);
Serial.begin(9600);
pinMode(A0, INPUT);
pinMode(10,OUTPUT);
}
void loop()
{
potRead = analogRead(A0);
analogWrite(10,potRead*0.2490234375);
brightness=amp*sin(2*3.1417*(1/period)*t);
if(brightness<0) brightness=-1*brightness;
analogWrite(heartpin,brightness);
// Serial.println("first block:");
// Serial.println(brightness
t++;
delayMicroseconds(d_time);
switch (state){
case 1:
if(t >= periodOne){
state = 2; //go to next state
amp = ampTwo;
period = periodTwo;
d_time = ontime;
t = 0; //reset t
}
break;
case 2:
if(t >= periodTwo){
state = 3; //go to next state
amp = ampThree;
period = ampThree;
d_time = ontime;
t = 0; //reset t
}
break;
case 3:
if(t >= periodThree){
state = 4; //go to next state
amp = 10;
period = periodOne; //not used until state = 1 again
d_time = offtime;
t = 0; //reset t
}
break;
case 4:
state = 1; //go back to state 1
amp = ampOne;
period = periodOne;
d_time = ontime;
t = 0; //reset t
break;
}
}
hi me n mac thankyou very much for your detailed description…
but the code is making the led blink much faster…not like the real heat now…and if i increase the delay…wouldn’t the adc be slower again ??
Perhaps you can start by explaining what it it you’re trying to do. First, what “sinewave of the heart” are you trying to copy ? Do you have a link to some description or picture ? You cite a period of 1667 usec which is 600 Hz. I know a human’s heart doesn’t beat that fast. If you’re trying to make the LED’s brightness vary every few usecs, it’s not going to work. The Arduino can’t change the PWM setting that quickly. The normal PWM period, w/o doing something special, is about 2000 usec. That is, you set the PWM duty cycle, and about 2000 usec later the entire PWM waveform has been clocked out … for just 1 PWM cycle. I don’t know what happens if the code trys to change the PWM setting before it has finished 1 cycle. You can speed up the PWM and shorten the period but it’s not clear to me what you will accomplish by that. Human vision doesn’t respond in the usec timeframe. All you will see is some average brightness, not one that changes every 131 usec (if you could make the Arduino do that).
Yes, if you increase some delays (ontime, offtime) the ADC will be read at longer intervals. Perhaps you should also tell us what you’re reading with it and how fast you really need it to be sampled. Immediately is not a viable answer. I added some time measurements to the code above and it takes about 470 usec to complete the loop. That’s how often the ADC is getting sampled with the above code. This time will be the same if I set the transistion periods back to what you had. That is the count of how many loops in each state happen before you go to the next state. I (probably a mistake) changed your 555’s everywhere to be 277, 555, 277. This makes the LED do it’s 2 blinks faster that your old code did. Here’s the new code but with those transition counts back to 555, 555, 555. See if that looks like your old code did (speed-wise). You can un-comment-out the println at the bottom of the loop if you want to see how long it take to go through the main loop() code. You can see it takes the same time to execute as the 277,555,277 code does. Do note that enabling the print will add a huge delay in the overall loop time because it takes a relatively long time to send the timing data to the serial monitor at 9600 baud.
#include<math.h>
double t;
double brightness;
const int heartpin=11;
// look at the sine wave of the heart, two cycles + one big cycle + two small cycle + bit flat part= eaual to 1667[µs]
// so one small cycle is eaual to
// so 1667/3 = 555 for each small big and small. and 555/2 for each 2 small cycles.
// so period = 277 [µs]
const double periodOne=277;
const double periodTwo=555;
const double periodThree=277;
double period = periodOne;
unsigned long time = 0;
const double ampOne=10;
const double ampTwo=150;
const double ampThree=10;
double amp = ampOne;
byte keyboard;
int ontime = 131;
int offtime = 425;
int d_time = ontime;
byte state = 1;
int potRead;
void setup()
{
pinMode(heartpin,OUTPUT);
Serial.begin(9600);
pinMode(A0, INPUT);
pinMode(10,OUTPUT);
}
void loop()
{
time = micros();
potRead = analogRead(A0);
analogWrite(10,potRead*0.2490234375);
brightness=amp*sin(2*3.1417*(1/period)*t);
if(brightness<0) brightness=-1*brightness;
analogWrite(heartpin,brightness);
// Serial.println("first block:");
// Serial.println(brightness
t++;
delayMicroseconds(d_time);
switch (state){
case 1:
if(t >= 555){
state = 2; //go to next state
amp = ampTwo;
period = periodTwo;
d_time = ontime;
t = 0; //reset t
}
break;
case 2:
if(t >= 555){
state = 3; //go to next state
amp = ampThree;
period = ampThree;
d_time = ontime;
t = 0; //reset t
}
break;
case 3:
if(t >= 555){
state = 4; //go to next state
amp = 10;
period = periodOne; //not used until state = 1 again
d_time = offtime;
t = 0; //reset t
}
break;
case 4:
state = 1; //go back to state 1
amp = ampOne;
period = periodOne;
d_time = ontime;
t = 0; //reset t
break;
}
//Serial.println(micros() - time);
}
As I mentioned in my original response, your for loops and my re-write aren’t doing what I think your comments indicate is supposed to happen. And I think that’s a good thing as hearts (human) don’t beat at 600 bps. Your variable “t” is not time but a counter. It counts how many times you went through the a for loop before going to the next for loop. It takes a certain amount of time to execute the code in that for loop, to do the brightness calculations, the analogWrite and the delay of “ontime”. My rewrite didn’t really change any of that but did add the analogRead of A0 and another analogWrite(). I said the analogRead() would take another 100+ usec and so if you wanted the timings to be the same you would need to reduced the “ontime” value from 131 to ??? usecs.
I just did some crude measurements of the times it takes to do the various sections of code. They are shown below.
(click on to open and enlarge)
(note: the switch case code for state = 1, 2, 3 take the same amount time to execute)
If you add up the times you can see how long it takes to do 1 pass of the main loop().
You can add up the sections that were in your for loops to see their approximate execution times.
If you add the sections up for all the states or all the for loops you can see how long it takes to go from heart beat to heart beat. It’s a lot longer than 1677 usec. Which, in real life, it should be (despite your code comments).
One last thing, I discovered something in your code that wasn’t the same in mine. For the long “offtime” delay … you have that in msecs and use the delay() function. I missed that and thought the “offtime” was in usec, like “ontime”. So I fixed that, and the code (below) now stays in state = 4 for the long “offtime”. If you reduce “ontime” to 0 or 1 usec (also done below) to account for the time it takes to do the new analog read and write (for the pot), you should see that the code now matches your original timing in all respects but reads the pot every ~ 340 usec.
#include<math.h>
double t;
double brightness;
const int heartpin=11;
// look at the sine wave of the heart, two cycles + one big cycle + two small cycle + bit flat part= eaual to 1667[µs]
// so one small cycle is eaual to
// so 1667/3 = 555 for each small big and small. and 555/2 for each 2 small cycles.
// so period = 277 [µs]
const double periodOne=277;
const double periodTwo=555;
const double periodThree=277;
double period = periodOne;
unsigned long time = 0;
unsigned long ST4time = 0;
const double ampOne=10;
const double ampTwo=150;
const double ampThree=10;
double amp = ampOne;
byte keyboard;
int ontime = 1; //short delay in usec
int offtime = 425; // long delay in msec
byte state = 1;
int potRead;
void setup()
{
pinMode(heartpin,OUTPUT);
Serial.begin(9600);
pinMode(A0, INPUT);
pinMode(10,OUTPUT);
}
void loop()
{
//time = micros();
potRead = analogRead(A0);
analogWrite(10,potRead*0.2490234375);
brightness=amp*sin(2*3.1417*(1/period)*t);
if(brightness<0) brightness=-1*brightness;
analogWrite(heartpin,brightness);
// Serial.println("first block:");
// Serial.println(brightness
t++;
delayMicroseconds(ontime);
switch (state){
case 1:
if(t >= 555){
state = 2; //go to next state
amp = ampTwo;
period = periodTwo;
t = 0; //reset t
}
break;
case 2:
if(t >= 555){
state = 3; //go to next state
amp = ampThree;
period = periodThree;
t = 0; //reset t
}
break;
case 3:
if(t >= 555){
state = 4; //go to next state
amp = 10;
period = periodOne; //not used until state = 1 again
t = 0; //reset t
ST4time = millis();
}
break;
case 4:
t = 0; //reset t all the time in state 4 so sin equals 0
if(millis() - ST4time > offtime){
state = 1; //go back to state 1
amp = ampOne;
period = periodOne;
//Serial.println(micros() - time);
//time = micros();
}
break;
}
//Serial.println(micros() - time);
}
FWIW I think the setting of the PWM for the LED as quickly as it’s done in the brightness calculations is something of a waste of time but it’s still in there in the code above.
Here are 2 timing diagrams that illustrate what your code does and what my re-write does.
If you look at your code, your 1’st thought to put the read of A0 at the end of the offtime delay, which meant that it happens only about once per second. Too infrequent for your purposes ? You could have put a read just before every for loop and then it would have been read about every 200 msec, except for the offtime delay, a period of about 400 msec. Still too infrequent ? Then you could have put a read of A0 inside of the 3 for loops but that wouldn’t solve the last issue, the 400 msec delay. So this is a pretty good example of why delays should be used with caution, because nothing else can be done when they are running (excepting interrupts). So look at my code (state = 4 stuff) and see how I didn’t use a delay but instead used a comparison of times. What I did was (effectively) put the read of A0 inside of every for loop and got rid of the long delay. In the rewrite there are no for loops, instead the main loop runs very frequently, doing the same calculations though with varying constants as state changes, with the read of A0 done in the main loop.
(click on to open and enlarge)
(click on to open and enlarge)
Hi me n mac …
This is the code i am trying to implement the human heart…
when we look at the human heart…it is somehow like sinewave…but like two sidebands with very less amplitude and one middle one with very high amplitude…the value i put in my algorithm are from the calculations…i made assuming the led to blink as the heart beat…blink smalll…grow…blink bigger…grow…then…again…smaller…and then dim for a while…like…small sine…then biiiiig sine…and then small sine …and then small dc…dim…the only thing we need to do is…connect the LED on the pin of the arduino board…I have had quite good results…but the only problem was…when i tried to implement the analogread function…it was not instantaneous…thank you alll for your valuable time and suggestions…