Go Down

Topic: pulseIn bug (Read 1 time) previous topic - next topic

september

OS Gentoo Linux
Arduino 0022 or 1.0.3 (any)
Standard example: Sensors --> Ping
Getting error during "Verify" process :

Code: [Select]
core.a(wiring_pulse.c.o): In function `pulseIn':
/usr/share/arduino-0022/hardware/arduino/cores/arduino/wiring_pulse.c:45: undefined reference to `__muluhisi3'
/usr/share/arduino-0022/hardware/arduino/cores/arduino/wiring_pulse.c:68: undefined reference to `__muluhisi3'
collect2: error: ld returned 1 exit status


Any ideas...

robtillaart

Never seen this one on Windows (my OS).

Can you open the faulty file and post the contents?
// my 0.22 IDE has perfectly meaningful code at line 45/68, no mentions of __muluhisi3 in the file.





Rob Tillaart

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

september

sure

file /usr/share/arduino-0022/hardware/arduino/cores/arduino/wiring_pulse.c:
Code: [Select]
/*
  wiring_pulse.c - pulseIn() function
  Part of Arduino - http://www.arduino.cc/

  Copyright (c) 2005-2006 David A. Mellis

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General
  Public License along with this library; if not, write to the
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  Boston, MA  02111-1307  USA

  $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
*/

#include "wiring_private.h"
#include "pins_arduino.h"

/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
* or LOW, the type of pulse to measure.  Works on pulses from 2-3 microseconds
* to 3 minutes in length, but must be called at least a few dozen microseconds
* before the start of the pulse. */
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
{
        // cache the port and bit of the pin in order to speed up the
        // pulse width measuring loop and achieve finer resolution.  calling
        // digitalRead() instead yields much coarser resolution.
        uint8_t bit = digitalPinToBitMask(pin);
        uint8_t port = digitalPinToPort(pin);
        uint8_t stateMask = (state ? bit : 0);
        unsigned long width = 0; // keep initialization out of time critical area

        // convert the timeout from microseconds to a number of times through
        // the initial loop; it takes 16 clock cycles per iteration.
        unsigned long numloops = 0;
        unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;

        // wait for any previous pulse to end
        while ((*portInputRegister(port) & bit) == stateMask)
                if (numloops++ == maxloops)
                        return 0;

        // wait for the pulse to start
        while ((*portInputRegister(port) & bit) != stateMask)
                if (numloops++ == maxloops)
                        return 0;

        // wait for the pulse to stop
        while ((*portInputRegister(port) & bit) == stateMask) {
                if (numloops++ == maxloops)
                        return 0;
                width++;
        }

        // convert the reading to microseconds. The loop has been determined
        // to be 20 clock cycles long and have about 16 clocks between the edge
        // and the start of the loop. There will be some error introduced by
        // the interrupt handlers.
        return clockCyclesToMicroseconds(width * 21 + 16);
}




problems in lines:
Code: [Select]
unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;
...
return clockCyclesToMicroseconds(width * 21 + 16);


it looks like there is something with definition of  clockCyclesToMicroseconds and microsecondsToClockCycles in
/usr/share/arduino-0022/hardware/arduino/cores/arduino/wiring.h file
Code: [Select]
#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) )
#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L )


thanks

robtillaart

What time out do you use?

Read this thread -http://arduino.cc/forum/index.php/topic,74813.msg563694.html#msg563694 -
See my reply msg10
Rob Tillaart

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

AWOL

Which board did you have selected?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

september

#5
Jan 20, 2013, 08:38 pm Last Edit: Jan 20, 2013, 09:00 pm by september Reason: 1

What time out do you use?

Read this thread -http://arduino.cc/forum/index.php/topic,74813.msg563694.html#msg563694 -
See my reply msg10


Thanks again.

I use standard examples Examples --> Sensors --> Ping from arduino package.
It looks like mistake in example
Code: [Select]
duration = pulseIn(pingPin, HIGH);
here no timeout

Tried your testcode from your thread (post #10), got just one (not two like before) error on line 68:
Code: [Select]
core.a(wiring_pulse.c.o): In function `pulseIn':
/usr/share/arduino-0022/hardware/arduino/cores/arduino/wiring_pulse.c:68: undefined reference to `__muluhisi3'
collect2: error: ld returned 1 exit status


Your fix is working only on for 45-th line.  :P
:)

september


september

Very interesting.
I made several tests with this easy code:
Code: [Select]
unsigned long duration;
int counter = 0;

unsigned long before = 0;
void setup()
{
  pinMode (5, INPUT);
  Serial.begin(9600);
}
void loop()
{
  duration = pulseIn(5, LOW, 10000000L); // yes 10.000.000
  {
    Serial.print("D: ");
    Serial.println (duration);
    Serial.print("M: ");
    Serial.println(millis()-before);
    before = millis();
  }
}

not working. I got:
Code: [Select]
core.a(wiring_pulse.c.o): In function `pulseIn':
/usr/share/arduino/hardware/arduino/cores/arduino/wiring_pulse.c:68: undefined reference to `__muluhisi3'
collect2: error: ld returned 1 exit status


File /usr/share/arduino/hardware/arduino/cores/arduino/wiring_pulse.c line 68 (original) :
Code: [Select]
return clockCyclesToMicroseconds(width * 21 + 16);

If I change it to:
Code: [Select]
return clockCyclesToMicroseconds(width * 2 + 16);
(I know that there no sense)   :smiley-red:
...there no any compilation errors.
As you can see I just changed "21" to "2"  :smiley-eek:
BTW, code with "3" :
Code: [Select]
return clockCyclesToMicroseconds(width * 3 + 16);
not working too.   :smiley-eek:

any ideas? :~

PS: Maximum value for "width" i have <= 736.

PPS: Gentoo Linux 64bit

robtillaart

Ha, now I recognize it you got the overflow bug!
I posted it here - http://code.google.com/p/arduino/issues/detail?id=675 - Solved in version 1.01 IIRC

OK explanation:

timeout = 10000000L  10 million

#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) )
#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L )

The first macro multiplies 10M * 1000 giving 10 000 000 000 which does not fit in a long !  overflow
The second similar.

Redefine these lines in wiring.h and it should work.
----------------------
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
// http://arduino.cc/forum/index.php/topic,74813.0.html
// #define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) )
// #define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L )

This should solve it,
Succes
Rob Tillaart

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

september

Right now I use Arduino 1.0.3

File /usr/share/arduino/hardware/arduino/cores/arduino/Arduino.h has the following definitions:
Code: [Select]
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )


F_CPU = 16 000 000
-----> clockCyclesPerMicrosecond = 16
"width" value (in my tests) was not more 736 (~550-736) ---> about 7-13 centimeters
(I temporary changed return value in wiring_pulse.c to get width from there)

File /usr/share/arduino/hardware/arduino/cores/arduino/wiring_pulse.c
Code: [Select]
return clockCyclesToMicroseconds(width * 21 + 16);

and problem still exists. :smiley-sad-blue:

robtillaart

736 * 21 + 16 = 15472 (should be an unsigned long as width is an unsigned long)
this is divided by 16 = 967
The math stays within the range.

// other line of thought
How much free ram has your application?
Which board are you using?

Can you post the complete sketch?  might give some clues..
Rob Tillaart

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

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy