analog function question

hi all,

I try to read the analog voltage from sensor echo, map the result, and adjust the PWM signal. The echo voltage is moving accordingly to the distance of the object. When I read and print the result, I see the printed result with echo signal and without echo are the same. I am not sure what's going on with my code. The echo signal I try to read is start with dc offset voltage is 2.5V, and it looks like sin wave up to 3V and down to 1V for 20 cycles. Please help if you have any ideas why my code has problem or if you can suggest better way to read this signal. I appreciate very much. Please see my code below.

unsigned long ultraValue = 0;            // assign the variable ultraValue to 0V and with no negative value (int positive max value= 32,767)             
  unsigned long ultraValue_ref = 0;        // assign the variable ultraValue_ref to 0V and with no negative value (long postive max=2,147,483,647)
  const int f40hz = 7; 
  const int f20hz = 8;
  const int pwm = 3;
  int ultraPwmValue = 0;
  int pulse = 0;
  
void setup()
{  digitalWrite(f40hz, HIGH);                               // set up to read the initial dc voltage later use to offset out the dc component
  for(int i = 0; i < 250; i++)                             // read for 250 times = 25ms. Reading rate 100us/read
  { ultraValue_ref = ultraValue_ref + analogRead(A1); }    // read echo analog voltage at pin A1 and store the differential positive voltage only 
  ultraValue_ref = ultraValue_ref / 250;
  digitalWrite(f40hz, LOW);  
}
 
 void loop()
{ 
   delayMicroseconds(100);                                           // delay 2ms before select the MUX to make sure noise not effect the reading
  digitalWrite(f40hz, HIGH);                                        // sets the pin high
  digitalWrite(f20hz, LOW);                                         // sets the pin low
  delayMicroseconds(500);                                           // delay another 100us after writing f40hz and f20hz to the MUX before reading echo at pin A1
  for(int i = 0; i < 250; i++)                                      // read for 250 times = 25ms. Reading rate 100us/read
  { ultraValue = ultraValue + analogRead(A1) - ultraValue_ref; }    // read echo analog voltage at pin A1 and store the differential positive voltage only      
  ultraValue = ultraValue / 250;                                    // averaging the reading value
  ultraPwmValue = map(ultraValue, 0, 1023, 235, 10);                // 0V map to 235 is equivalent to 90% (~30ms) on time of 33ms, 1023(~5V) map to 10 is 6.6% (~2ms) on time of 33ms  
  analogWrite(pwm, ultraPwmValue);                                  // write analog value to pin3 by changing the pulsewidth of pwm
  pulse = pulseIn(pwm, HIGH);                                       // measure the pin3 pulsewidth
  digitalWrite(pwm, LOW);                                           // force pwm to low after pulsewidth goes low to make sure pulsewidth not on again until next cycle
  digitalWrite(f40hz, LOW);      
  
}

I try to read the analog voltage from sensor echo

What sensor?

  digitalWrite(f40hz, HIGH);                                        // sets the pin high
  digitalWrite(f20hz, LOW);                                         // sets the pin low

Do these comments contribute anything?
Useless comments should be removed.

  delayMicroseconds(500);                                           // delay another 100us after writing f40hz and f20hz to the MUX before reading echo at pin A1

Ditto for WRONG comments.

hi Pauls,

thanks for your reply. I try to read the echo analog singal from ultrasonic sensor. Please ignore my comments since I change the code, but I did not fix the comment. Do you see the problem with my code? The result when I print it out is the same with and without echo singnal.

Thanks!!!

Pop quiz: What is the average value of a sine wave?

Jiggy-Ninja:
Pop quiz: What is the average value of a sine wave?

Over what range of angles?

PaulS:

Jiggy-Ninja:
Pop quiz: What is the average value of a sine wave?

Over what range of angles?

Let's go with "over multiple cycles"

And, to also be clear, I am referring to the mean value, which is what the OP appears to be calculating.

Also, from the OP:
"When I read and print the result,..."

I don't see any Serial.print() in that code, nor do I see any results posted. We have no clue what values you're getting or what values you're even looking at. There could be multiple things wrong, including

  • Not getting the timeframe for the echo right.
  • Not sampling fast enough.
  • Incorrect detection algorithm (what I alluded to with my pop quiz)

A datasheet or product link to your echo sensor is also helpful, so we know (and don't guess) what hardware you're using and how it works.

hi all,

thanks for your reply. sorry I did not include the print function in the code I posted, but I had it. In fact, I monitor the waveform with scope and print the result through serial monitor. I am aware of the sin wave will return the dc voltage only (in this case 2.5V dc) if do averaging. But look at my function I defined, this will not allow negative number.

unsigned long ultraValue = 0;
unsigned long ultraValue_ref = 0;
.
.

and this line of code

{ ultraValue = ultraValue + analogRead(A1) - ultraValue_ref; }

will store 0V into ultraValue if ultaValue + analogRead(A1) is smaller than 2.5V. I am right?

will store 0V into ultraValue if ultaValue + analogRead(A1) is smaller than 2.5V. I am right?

No. You are free to actually store the value returned by analogRead() and Serial.print() that value. Perhaps doing so would be revealing.

hi PaulS,

No. You are free to actually store the value returned by analogRead() and Serial.print() that value. Perhaps doing so would be revealing.

if that the case, how can I read the analog voltage above 2.5V only and ignore the one below 2.5V?
can you help to give me some way of code to read this?

thanks in advance.

how can I read the analog voltage above 2.5V only and ignore the one below 2.5V?

You could put some hardware in front of your input, or you could read all values and filter the one you're interested in in software.

Incorrect detection algorithm it is, then.

and this line of code

{ ultraValue = ultraValue + analogRead(A1) - ultraValue_ref; }

will store 0V into ultraValue if ultaValue + analogRead(A1) is smaller than 2.5V. I am right?

You are wrong. Unsigned numbers do not work that way. You need to implement that check. One thing you can do is this:

{ ultraValue = ultraValue + abs(analogRead(A1)-ultraValue_ref); }

Adding the absolute value of the difference between the reference and measured voltage will give you only a positive number.

Or you could use peak/valley detection, storing a running maximum/minimum of the signal and use that to calculate the wave's intensity and set the PWM.

hi all,

thanks for your inputs. I try your suggestion and ask again if I still have problem.

thanks again.