Pages: [1]   Go Down
Author Topic: pulseIn bug  (Read 1487 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
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...
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 224
Posts: 13917
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.





Logged

Rob Tillaart

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

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

sure

file /usr/share/arduino-0022/hardware/arduino/cores/arduino/wiring_pulse.c:
Code:
/*
  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:
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:
#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) )
#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L )

thanks
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 224
Posts: 13917
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What time out do you use?

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

Rob Tillaart

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

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26534
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Which board did you have selected?
Logged

"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.

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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:
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.  smiley-razz
 smiley
« Last Edit: January 20, 2013, 03:00:18 pm by september » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Which board did you have selected?
Arduino Uno
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Very interesting.
I made several tests with this easy code:
Code:
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:
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:
return clockCyclesToMicroseconds(width * 21 + 16);

If I change it to:
Code:
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:
return clockCyclesToMicroseconds(width * 3 + 16);
not working too.   smiley-eek

any ideas? smiley-confuse

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

PPS: Gentoo Linux 64bit
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 224
Posts: 13917
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Rob Tillaart

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

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Right now I use Arduino 1.0.3

File /usr/share/arduino/hardware/arduino/cores/arduino/Arduino.h has the following definitions:
Code:
#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:
return clockCyclesToMicroseconds(width * 21 + 16);

and problem still exists. smiley-sad-blue
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 224
Posts: 13917
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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..
Logged

Rob Tillaart

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

Pages: [1]   Go Up
Jump to: