tried modifying the code but output always shows “out of range”.
*/
#define trigPin PA6
#define echoPin PA7
#define led PA4
#define led2 PB0
void setup() {
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(led, OUTPUT);
pinMode(led2, OUTPUT);
Serial.begin (115200);
}
looks like this must be something added in Arduino 1.0 API, and no one else has noticed its missing
i will get back to you shortly
we need to add a function for this
This is the SAM version
/*
Copyright (c) 2011 Arduino. All right reserved.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "Arduino.h"
#include "wiring_private.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. */
extern uint32_t pulseIn( uint32_t pin, uint32_t state, uint32_t 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.
PinDescription p = g_APinDescription[pin];
uint32_t 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 22 clock cycles per iteration.
uint32_t numloops = 0;
uint32_t maxloops = microsecondsToClockCycles(timeout) / 22;
// wait for any previous pulse to end
while (PIO_Get(p.pPort, PIO_INPUT, p.ulPin) == state)
if (numloops++ == maxloops)
return 0;
// wait for the pulse to start
while (PIO_Get(p.pPort, PIO_INPUT, p.ulPin) != state)
if (numloops++ == maxloops)
return 0;
// wait for the pulse to stop
while (PIO_Get(p.pPort, PIO_INPUT, p.ulPin) == state) {
if (numloops++ == maxloops)
return 0;
width++;
}
// convert the reading to microseconds. The loop has been determined
// to be 52 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 * 52 + 16);
}
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) )
#define microsecondsToClockCycles(a) ( (a) * (F_CPU / 1000000L) )
/* 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. */
uint32_t pulseIn( uint32_t pin, uint32_t state, uint32_t 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.
gpio_dev *dev=PIN_MAP[pin].gpio_device;
uint32_t bit = (1U << PIN_MAP[pin].gpio_bit);
uint32_t 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 22 clock cycles per iteration.
uint32_t numloops = 0;
uint32_t maxloops = microsecondsToClockCycles(timeout) / 22;
// wait for any previous pulse to end
while ( (dev->regs->IDR & bit) == state)
if (numloops++ == maxloops)
return 0;
// wait for the pulse to start
while ((dev->regs->IDR & bit) != state)
if (numloops++ == maxloops)
return 0;
// wait for the pulse to stop
while ((dev->regs->IDR & bit) == state) {
if (numloops++ == maxloops)
return 0;
width++;
}
// convert the reading to microseconds. The loop has been determined
// to be 52 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 * 52 + 16);
}
I’ve not tested it, and we’d also need to look at the code dissasembly to see how many cycle it takes in each of the while loops.
The Due code has 16 cycles per while loop, the STM32 may be different,
But you may as well give it a go, and let us know if it vaguely works
I can do it properly tomorrow using the square wave generator on my scope, but I can’t do it now because its getting to late and I’ve had a hard day
But I will need to put the function in an F1 specific file, or probably just have a wrapper in wirish_digital, and then call a processor specific implementation of the low level stuff
FYI
I have found what appears to be a bug in pulseIn on both AVR and SAM
I’ve done an issue on GitHub
https://github.com/arduino/Arduino/issues/3112
This has now been implemented.
Its a change deep in the core, so I’d recommend you just download the repo again and replace all your files
Note
I have only tested using my oscilloscope using a 1khz square wave, but I have calibrated to this.
I don’t think pulseIn is guaranteed to be that accurate on either AVR or Due, as it doesnt take into account the time for any interrupts.
But I’ve used the same base code as AVR and Due (SAM) so the implementation should give similar results to the Due
I have noticed there are at least 10 bugs logged on GitHub against pulseIn for various reasons, and I’ve logged another because the AVR and Due code doesn’t do what the API spec says it does, in terms of the timeout.
Edit
Looking on the old leaflabs site, it looks like 2 other functions are not implemented
tone(): TODO
noTone(): TODO
pulseIn(): TODO
So I guess we ( i ) need to look at how to code these. I’ll put it on my To Do list
FYI
I have found what appears to be a bug in pulseIn on both AVR and SAM
I’ve done an issue on GitHub
https://github.com/arduino/Arduino/issues/3112
Yes. You can measure this by either coding to wait for rising edge or use attach interrupt.
I posted a simple sketch however that works viewtopic.php?f=44&t=106
Porting of NewPing is a separate issue, as its AVR only and probably uses interrupts
The STM32 has some fancy features where the hardware timers can use external interrupts, however for now, I thought it was most expedient just to port the Arduino (SAM) code to STM32 for the greatest compatibility
Please feel free to write a version or NewPing etc which uses the STM32 hardware to the best of its abilities
https://github.com/arduino/Arduino/comm … ba533d12ef
We may be able to use it
* AVR+SAM: reworked pulseIn() function to become GCC agnostic
* AVR+SAM: added pulseInLong() (based on micros()) to help getting good results in interrupt-prone environments
This is something to keep on the To Do list