Go Down

Topic: basic arithmetic doesn't work (Read 1 time) previous topic - next topic

gridzbispudvetch

I'm trying to make an echolocation device. Here's my code:

Code: [Select]
#include <Servo.h>;
Servo motor;
const int pingpin = 3;
const int echpin = 4;
int deg = -80;
int sofar;

long duration;
float distance;
void setup() {
  // put your setup code here, to run once:
  motor.attach (9);
  pinMode (pingpin, OUTPUT);
  pinMode (echpin, INPUT);
  Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:
  do
  {
  digitalWrite (pingpin, LOW);
  delayMicroseconds (2);
  digitalWrite (pingpin, HIGH);
  delayMicroseconds (10);
  digitalWrite (pingpin, LOW);
  sofar = micros();
  while(digitalRead(echpin) != LOW) { }; // do nothing
  duration = micros()-sofar;
  distance = duration*0.034/2;
  Serial.print("Distance: ");
  Serial.println(distance);
  deg = (deg+1);
  motor.write((motor.read() - .1));
  delayMicroseconds (50);
  }while (!deg>80);

  }

 
  The line that says

Code: [Select]
  duration = micros()-sofar;

doesn't work. The duration is always printed as equal to micros.

gfvalvo

#1
Mar 23, 2018, 03:14 am Last Edit: Mar 23, 2018, 03:40 am by gfvalvo
I guarantee you that arithmetic on the processor "works". That it doesn't do what you expect simply means your expectations are incorrect.

It's a poor craftsman that blames his tools.
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

larryd

#2
Mar 23, 2018, 03:21 am Last Edit: Mar 23, 2018, 03:22 am by larryd
int sofar;

micros()
Returns the number of microseconds since the Arduino board began running the current program.(unsigned long)

sofar = micros();

Hum, what could be wrong.



No technical PMs.
If you are asked a question, please respond with an answer.
If you are asked for more information, please supply it.
If you need clarification, ask for help.

jremington

Why is it that beginners so often blame the compiler, or the processor, for their lack of understanding of the programming language?

DKWatson

  sofar = micros();
  while(digitalRead(echpin) != LOW) { }; // do nothing
  duration = micros()-sofar;

You just set sofar to equal micros and then you subtract it from micros. Isn't that kinda like a-a and aren't you always going to end up with zero?

Bear in mind that if you change nothing w.r.t. timer0, the resolution of micros() is 4us. That's 64 clock cycles. A lot can happen in 64 ticks, especially if echpin is LOW. If you're looking to get high resolution timing, better to use timer1 or 2 with no prescaler and then log TCNT before and after. That way you're counting 62.5ns ticks. Even a prescaler of 8 will give you half micro ticks and millimeter resolution. The default prescaler is 64 and a bit granular for high-speed timing.

If none of that seems like it works, double check what values you're getting on your echo pin. If you want a low to kick in to stop/start the timing, do you have a pull-down resistor on the pin or does it just float? Floating inputs are not helpful if you want a valid reading to make a decision.
Live as if you were to die tomorrow. Learn as if you were to live forever. - Mahatma Gandhi

CrossRoads

No, the 2nd micros() will return  a slightly bigger (or much  bigger) number than the 1st  micros(), depending on how long it takes for the digitalRead to return HIGH.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

TommiP

#6
Mar 23, 2018, 05:34 am Last Edit: Mar 23, 2018, 05:36 am by TommiP
Why is it that beginners so often blame the compiler, or the processor, for their lack of understanding of the programming language?
It's much easier to blaim someone else, I've used to that while I've been working around the army.. Stabbing in the back is also quite common..

TommiP

cattledog

#7
Mar 23, 2018, 05:46 am Last Edit: Mar 23, 2018, 05:47 am by cattledog
Take a look at this data sheet for the HC SR04 https://www.electroschematics.com/wp-content/uploads/2013/07/HCSR04-datasheet-version-1.pdf

The digitalRead() of the echo pin is LOW right after the trigger, and the while statement is not pausing the program and sofar and micros will have the same value.

Code: [Select]
while(digitalRead(echpin) != LOW) { }; // do nothing
sofar = micros();

robtillaart

try this

Code: [Select]
#include <Servo.h>;

Servo motor;

const int pingpin = 3;
const int echpin = 4;

int deg = -80;
unsigned long sofar;
unsigned long duration;
float distance;


void setup()
{
  Serial.begin(9600);
  Serial.println(__FILE__);

  motor.attach (9);

  pinMode (pingpin, OUTPUT);
  pinMode (echpin, INPUT);
}

void loop()
{
  do
  {
    digitalWrite (pingpin, LOW);
    delayMicroseconds (2);

    digitalWrite (pingpin, HIGH);
    delayMicroseconds (10);

    digitalWrite (pingpin, LOW);
    sofar = micros();

    while(digitalRead(echpin) != LOW) { }; // do nothing

    duration = micros() - sofar;
    distance = duration * 0.034/2;

    Serial.print("Distance: ");
    Serial.println(distance);

    deg = deg + 1;
    motor.write((motor.read() - .1));
    delayMicroseconds (50);

  } while (! (deg > 80));

}


CTRL-T auto indents the code for better readability.
Added also some blank lines to separate some logic visually for same reason.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

motor.write((motor.read() - .1));

don't know if the write accepts floats ...
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

DKWatson

No, the 2nd micros() will return  a slightly bigger (or much  bigger) number than the 1st  micros(), depending on how long it takes for the digitalRead to return HIGH.
In a perfect world you'd be correct, and the code would be working as well. If while(digitalRead(echpin) != LOW) { }; fails, i.e. echpin is LOW, the code falls straight through, and it's going to do so in a lot less than 4us, ergo a-a will still equal zero.
Live as if you were to die tomorrow. Learn as if you were to live forever. - Mahatma Gandhi

robtillaart

#11
Mar 23, 2018, 03:51 pm Last Edit: Mar 23, 2018, 03:53 pm by robtillaart
In a perfect world you'd be correct, and the code would be working as well. If while(digitalRead(echpin) != LOW) { }; fails, i.e. echpin is LOW, the code falls straight through, and it's going to do so in a lot less than 4us, ergo a-a will still equal zero.
how much time does a digitalRead() takes ? 

The while (condition) is a compare and a jump so 2 clockcycles ~1/8 uSec.

Code: [Select]
uint32_t start;
uint32_t stop;

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);

  start = micros();
  int x = digitalRead(5);
  stop = micros();

  Serial.println(x);
  Serial.println(stop);
  Serial.println(start);
  Serial.println(stop - start);
}

void loop(){}


output (UNO, IDE1.8.5)  --> gives 8uSec for one call to digitalRead()

1
1504
1496
8
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

DKWatson

Depends on whether the pin is configured for PWM. If so, about 5.1us (based on 20,000 iterations), else about half. bitRead(port,pin) is only 2 clock cycles. Every other permutation is between.
Live as if you were to die tomorrow. Learn as if you were to live forever. - Mahatma Gandhi

cattledog

#13
Mar 23, 2018, 04:43 pm Last Edit: Mar 23, 2018, 04:56 pm by cattledog
Quote
If while(digitalRead(echpin) != LOW) { }; fails, i.e. echpin is LOW, the code falls straight through
Correct, and the echo pin is LOW for aprproximately 200 microseconds after the trigger post. Then it goes HIGH for a period which indicates the distance.  This is shown in the data sheet linked in reply #7.

Typically the blocking proceedures for reading this device uses pulseIn(HIGH) which waits for the pulse to go high before starting the timing. When using non blocking interrupt techniques, you must detect the echo pulse going HIGH and then LOW.

Code: [Select]
volatile unsigned long LastPulseTime;
int duration;
const byte trigPin = 7;
const byte echoPin = 2;
//const byte echoPin = 3;
volatile boolean pulseCaptured = false;
boolean triggerFinished = false;

void setup()
{
  Serial.begin (9600);
  Serial.println("starting...");
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  attachInterrupt(0, EchoPinISR, CHANGE); // Pin 2 interrupt on any change
  // attachInterrupt(1, EchoPinISR, CHANGE);  // Pin 3 interrupt on any change
}

void loop()
{
  if (triggerFinished == false)
  {
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    triggerFinished = true;
  }

  if (pulseCaptured == true && triggerFinished == true)
  {
    pulseCaptured = false; //reset
    triggerFinished = false;
    Serial.print((LastPulseTime / 2) / 29.1, 1);
    Serial.println("cm");
  }
}

void EchoPinISR()
{
  static unsigned long startTime;

  if (digitalRead(echoPin)) // Gone HIGH
    startTime = micros();
  else  // Gone LOW
  {
    LastPulseTime = micros() - startTime;
    pulseCaptured = true;
  }
}



DKWatson

Now this is reaching, but if you've copied and pasted code, you never really know how the non-character characters get carried across. I've wasted a lot of time distinguishing quotes.

With  duration = micros()-sofar; simply try re-typing it and see what happens and then throw a couple of free parentheses into the mix  duration = (micros()-sofar); just for fun. See what happens.
Live as if you were to die tomorrow. Learn as if you were to live forever. - Mahatma Gandhi

Go Up