Closed MyVanitar closed 2 years ago
Please follow the picture (Tiny85-No bootloader, 8MHz Internal) and you can simply program the chip using the Arduino generated HEX
file.
The code uses pulseIn() to determine the distance. This is an Arduino library function which is limited in accuracy. As the clock of your board 8Mhz, the accuracy is I think 8 us at best (If there are no other interrupts etc)
and with many fluctuations up to 100cm
For that reason I added different reading modes which takes the median or average of multiple samples. That improves the accuracy. Which mode to use depends on the amount of noise in your system.
In most cases the average mode with 4 or 8 samples will work, otherwise you might increase the number of samples used of use the median mode. This latter mode just selects the middle sample when you sort them in size. The advantage is that outliers are ignored, drawback is that is takes more CPU cycles. The number of samples for median is ideally an odd number (5,7,9 ..) .
My main problem is not the fluctuations, however the range is very limited. The fluctuation happens near the maximum range, however in my case the range does not go higher than 100cm.
if you think the 8MHz clock is the cause of the problem, I can increase it to 20MHz external to see what happens, however the problem is that the pins are limited and used by the SRF05 module itself.
I need to install ATTINY boards to investigate how the pulsein() function looks like.
I need to install ATTINY boards to investigate how the pulsein() function looks like.
You just need to have one ATTiny85 chip and an AVR programmer (such as USBasp) to check this.
By the way, I have also tested this using the NewPing
library, and the problem happened there also. The detection range was limited.
I don't have a tiny85 around.
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);
// convert the timeout from microseconds to a number of times through
// the initial loop; it takes approximately 16 clock cycles per iteration
unsigned long maxloops = microsecondsToClockCycles(timeout)/16;
unsigned long width = countPulseASM(portInputRegister(port), bit, stateMask, maxloops);
// prevent clockCyclesToMicroseconds to return bogus values if countPulseASM timed out
if (width)
return clockCyclesToMicroseconds(width * 16 + 16);
else
return 0;
}
The pulseIn() calls an assembly routine countPulseASM() which is register optimized for AVR
From the library the "C code equivalent"
unsigned long pulseInSimpl(volatile uint8_t *port, uint8_t bit, uint8_t stateMask, unsigned long maxloops)
{
unsigned long width = 0;
// wait for any previous pulse to end
while ((*port & bit) == stateMask)
if (--maxloops == 0)
return 0;
// wait for the pulse to start
while ((*port & bit) != stateMask)
if (--maxloops == 0)
return 0;
// wait for the pulse to stop
while ((*port & bit) == stateMask) {
if (++width == maxloops)
return 0;
}
return width;
}
Code wise it will be very hard or impossible to optimize this code. The good news is that it could measure with a higher accuracy than I expected, probably 2 us .
As the speed of sound is ~340.000 mm per second 0.34 mm per microsecond. So the ultimate accuracy could in theory be around 1 mm. In practice this is not feasible.
Inaccuracy for longer times can come from interrupts that occur during the pulseIn()
So is your code using interrupts?
So is your code using interrupts?
Well, No, I just have one SSD1306 I2C LED module connected. I'm not sure if that causes this. I try to port it with a different library. What I use now is Tiny4kOLED
I assume you do not write to the display in the background so that should not cause interrupts.
By the way, I have also tested this using the NewPing library, and the problem happened there also. The detection range was limited.
What does the datasheet of the SRF tell about range etc?
I assume you do not write to the display in the background so that should not cause interrupts.
The code is very simple. This is the loop, apart from this is just initialization.
void loop() {
oled.setCursor(0, 2);
oled.print(SRF.getCentimeter(), 1);
oled.setCursor(0, 4);
oled.print(SRF.getInch());
delay(100);
}
What does the datasheet of the SRF tell about range etc?
it is the SRF05 module Sensor. it says up to 450cm. The module might be bad? I'm not sure really!
The module might be bad?
That is an option, you can do some simple testing e.g 10 20 30 40 50 cm and how accurate it measures them and where it stops measuring.
The module might be bad?
That is an option, you can do some simple testing e.g 10 20 30 40 50 cm and how accurate it measures them and where it stops measuring.
it is good up to 70cm and accurate, after that it sucks.
70 cm is definitely not 450 cm..
Can you try the sensor with an UNO or ESP32?
If these give a similar (too) short range it would point towards the sensor.
A SRF has a PIC microprocessor on it. 5 pins on the board are to program it (not disclosed how). An option is that the code of the PIC is corrupted.
The library has this line uint32_t duration = pulseIn(_echo, HIGH, 300000); so it measures at most 300.000 us = 0.3 seconds that is equivalent to ~100 meters...
So library is not limiting on distance.
I tested the SRF05 module with Arduino-UNO board and it works as expected.
If the UNO with SRF works ok, it is the tiny85 (compiler?)
some thoughts:
Garbage begins around 70 cm ==> approx 200 microseconds At least that is no magic computer number that rings a bell.
Clock speed: to be tested with 16 MHz Tiny85 if possible
out of memory: if stack meets heap , strange things can happen. UNO code that might work on the tiny85.
uint32_t freeRam()
{
extern int __heap_start, *__brkval;
int v;
return (uint32_t) &v - (__brkval == 0 ? (uint32_t) &__heap_start : (uint32_t) __brkval);
};
protocol error:? do you have a logic analyzer to investigate? Alternatively measure the pulses between tiny85 and srf with your UNO.
I got tired of this since this is either the compiler problem or the unknown chip limitations. Arduino is not a stable platform to count on it for all scenarios. the freeRam()
shows 369 as return. I can not use an external crystal on the pins since they are already equipped.
Ok, RAM seems to be no limitation.
You might ask the question on the Arduino forum. There are definitely people with more tiny specific experience than I have. If you do and get some good cause analysis ir even a solution please let me know as it might help to improve the library in the future.
Hello,
I used this library on
ATTiny85
MCU. I useATTinyCore
board manager. The best performance is up to 70cm, and with many fluctuations up to 100cm. I think it is the timing issue. Could you please investigate? The clock is 8MHz, internal.