ESP8266 "ovf" when doing small double maths - arduino

I'm using a Wemos D1 based on the ESP8266 wifi chip with the Arduino C framework to do some simple small math.
As far as I can gather, double precision is available so I'm using it - with a maximum of something like 1.8*10^103.
But I'm getting an ovf when I try to calculate a number around 5*10^8.
Any ideas please?
void setup(){
Serial.begin(9600);
while(!Serial);
Serial.println("Hit any key to start math");
double te = 6800;
double res = te * te;
Serial.println(res);
te = 68000;
res = te * te;
Serial.println(res);
te = 680000;
res = te * te;
Serial.println(res);
}
void loop(){
}
Prints
46240000.00
ovf
ovf

Arduino does supports 4-byte double data type. and your code is indeed produced a valid double value that is not overflow (ovf).
The problem that you see has to do with the way Arduino implement Serial.print() function which is almost like a half-cooked hack to support floating-point and is not as reliable as vprintf() that is available in avr-libc. You can see the source code here which print ovf for anything bigger than 4294967040.0 or smaller than -4294967040.0. I thought that ESP8266 Arduino Core has fixed this instead of inheriting the ugly implementation of Arduino Serial.print(), but apparently not.
Luckily the ESP8266 Arduino Core does have a Serial.printf() method that provide better floating point rendering. This code will shows that your number is indeed a valid number for double data type.
void setup(){
Serial.begin(9600);
while(!Serial);
double te = 68000;
double res = te * te;
Serial.println(res); //this will produce 'ovf'
Serial.printf("Result=%f\n", res); //this will produce correct 4624000000.000000
}
Please noted that Serial.printf() is ESP8266 specific implementation to support full floating point vprintf() in the standard library. It is not available for standard Arduino Boards.
For Arduino boards, there is a way to use sprintf() which inherits from vprintf() to print the correct floating point with some twist on linker options during code compilation process. I have a blog post Do you know Arduino - sprintf() and floating point talk about how to do that.

Related

How to read the reset vector on an ATMEGA328

I have several ATMEGA328 based custom boards: I recently found that the standard Arduino bootloader does not handle watchdog timeouts correctly (it keeps resetting, so the device is effectively bricked until the next power cycle) so I am switching to the Optiboot bootloader.
I want to add something to my app that tells me whether the bootloader is Arduino or Optiboot. As Optiboot is a lot smaller, the reset vector is different, so printing that out would be a good indication.
Serial.println (pgm_read_word_near(0), HEX);
The above line of code prints out 940C, and I was expecting something like 7E00. How can I print out the address from the reset vector?
The actual address of the start of the boot flash section is determined by the BOOTSZ fuses.
This reads the size of the bootloader for classic ATmega:
uint32_t bootloaderSize;
cli();
uint8_t highBits = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
sei();
if (!(highBits & bit(FUSE_BOOTRST))) {
uint8_t v = (highBits & ((~FUSE_BOOTSZ1 ) + (~FUSE_BOOTSZ0 )));
bootloaderSize = MIN_BOOTSZ << ((v >> 1) ^ 3);
}
use #include <avr/boot.h>

Arduino ESP32 TwoWire "method" doesn't work

I have trouble using two sensors on two I2C interfaces.
The problem is, that I when I try to replace the Wire.begin() with something like this: I2C.begin(21, 22), my sensor QMC5883L returns for x, y and z 0. I included the Wire library manually and created a TwoWire object:
#include <Wire.h>
TwoWire I2C = TwoWire(0);
When I tried this, I commented the _wire->begin() in the library, It worked with the commented line and with Wire.begin() in the sketch, but when I try to replace Wire.begin() with I2C.begin(21, 22) it doesn't work anymore.
The reason, why this should work is that I want to create 2 interfaces like that and then give them to the compass.begin(&I2C) method. In the library I have this:
void QMC5883LCompass::init(TwoWire *theWire){
_wire = theWire;
_wire->begin(); // this is the line I commented, when getting the zeros...
_writeReg(0x0B,0x01);
setMode(0x01,0x0C,0x10,0X00);
}
Did I forget something?
Problem is that when calling _wire->begin() is actually calling the default definition (from Wire.h):
bool begin(int sda=-1, int scl=-1, uint32_t frequency=0);
Default parameters -1 for SDA/SCL means default pins, wich overwrites the ones you added in the first begin(...)
Presuming you are using https://github.com/mprograms/QMC5883LCompass, the solution is to subclass QMC5883LCompass and override the void QMC5883LCompass::init() or create a new init(...) with your specific needs.

How do I rotate 2 steppers at the same time?

Is there somethimg like theading in arduino?
I'm using Stepper.h library to use steppers and I want to rotate two of them at the same time, is that possible?
Additional info:
I'm using two drivers ULN2003 and Arduino Nano to controll steppers.
Code for one of them:
void AStep(){
AStepper.step(i1.toInt());
display.println("Turned A stepper;");
display.display();
}
You can make them appeir as they are moving at the some time by making the stepper do smaller "steps".
The only thing is that this method DOESN'T make them turn in actual sync.
Snippet by PaulS from the Arduino forums.
for(int s=0; s<step_360; s++)
{
AStepper.step(1);
BStepper.step(1);
}

Serial.print() truncates data when reading with QSerialPort

I am trying to write a simple integer value from an Arduino Mega 2560 to a Qt Application. Baudrate is set to 9600 and Serial.read() works fine when I send data through an open port with serial->write(some_data); from Qt Application.
digitalWrite(SS, LOW);
if (Serial.available() == 2) {
response1 = SPI.transfer(Serial.read());
response2 = SPI.transfer(Serial.read());
}
digitalWrite(SS, HIGH);
The above code works fine. I read another by before and had to add delay(3) to make this work. Now I want to send back the response
Serial.print((response2 << 8 ) | (response1 & 0xFF));
But there are always truncated digits. I know from the logic analyzer that the response is e.g. 8193 so with QByteArray b = serial->readAll(); I get results like 8, 81, 819, and sometimes 8193. I.e.: always the last digits are truncated randomly. I assume that this is also a timing issue but I could not find a fix for this.
Just in case anyone facing the same issue: Changing the Baudrate from 9600 to 112500 fixed this.

Arduino's analogRead() returns junk when I print via serial

I'm making a clock with the Arduino, and I want to make a button to set the time.
So, just to test, I pluged a wire in the Analog Input pin 0 and wrote two lines of code to read the pin and print it via Serial, but all I get is junk.
valm = analogRead(0);
Serial.println(valm);
And what I get from the serial monitor is this:
?j?d?±µ?Ê??jDd?±µ???ºjRd?±µ???ºj?d?±µ?Ê??j?d?±µ?É?ªjRd?±µ???ÊjRd?±µ???Âj?d?±µ????j?d?±µ?É??j
Rd?±µ????j?d?±µ???ºj?d?±µ?É??jRd?±µ????j?d?±µ?Ê?ÊjDd?±µ???Âj?d?±µ????j?d?±µ?É??jRd?±µ????j?d
?±µ?É?ÂjRd?±µ???Êj?d?±µ???ªj?d?±µ?Ê?Êj$d?±µ???ÂjRd?±µ????j?d?±µ????jdd?±µ????jRd?±µ???Âj?d?±
µ?É?ÊjRd?±µ????j?d?±µ?Ò?Êj?d?±µ?É?ÂjRd?±µ????j?d?±µ????j?d?±µ?É??jRd?±µ???Âj?d?±µ???Êj?d?±µ?
??ªj?d?±µ???Êj?d?±µ???ÂjRd?±µ????j?d?±µ????j?d?±µ?É??jRd?±µ???Âj?d?±µ?Ò?Êj?d?±µ?É?ªj?d?±µ?É?
?jTd?±µ???Âj?d?±µ????j?d?±µ?É??jRd?±µ????j?d?±µ?É?ÂjRd?±µ???Êj?d?±µ?É?ªjRd?±µ???Êj?d?±µ???ºj
?d?±µ?È??jTd?±µ????jRd?±µ???ªj?d?±µ?È?ÂjTd?±µ?É?ÊjRd?±µ???ªj?d?±µ???Êj?d?±µ???ºj?d?±µ?É??jRd
?±µ???Êj?d?±µ???ªj?d?±µ?É?ÂjPd?±µ???Êj?d?±µ???ªj?d?±µ?Â?Êj?d?±µ?É?ºjRd?±µ????j?d?±µ?É??jRd?±
µ???ªj?d?±µ?Ê?Âj?d?±µ???ÊjRd?±µ???ªj?d?±µ?Ò?Êj?d?±µ???ºjRd?±µ????j?d?±µ???Êj?d?±µ?Ê?ªjdd?±µ?
??ÂjRd?±µ???Âj?d?±µ?É?ªjPd?±µ???Êj?d?±µ????j?d?±µ?É??jRd?±µ???Êj?d?±µ?É?ªjdd?±µ???ÂjRd?±µ???
Âj?d?±µ?É?ªjDd?±µ???Êj?d?±µ?Ê??j?d?±µ?É??jRd?±µ???ÊjRd?±µ???ªj?d?±µ?Ê?ÂjPd?±µ???Âj?d?±µ???ªj
?d?±µ?É?Êjdd?±µ?É??jRd?±µ????j?d?±µ?É?Êj$d?±µ???ªjRd?±µ???Âj?d?±µ?Â?ÂjTd?±µ???ªj?d?±µ???Êj?d
?±µ????jRd?±µ????j?d?±µ?É?ÊjTd?±µ???ªjRd?±µ???Âj?d?±µ???Âj?d?±µ?É?ªjRd?±µ???ÊjRd?±µ?Ò??jTd?±
µ????j?d?±µ???Êj
Why?
Edit:
I had set the digital pin 0 to output, and I thought maybe that was the problem so I went to the Arduino website and found the page Analog Input Pins.
So I tried to read from pin 14 which they say is the analog input pin 0, but I got the same output.
By the way, I'm trying to read from the analog only pins, not the one wich are also digital.
Try running this sample code found on the Arduino website. You shouldn't need to convert the variable valm or anything.
/*
Analog input
Reads an analog input on analog in 0, and prints the value out.
Created 24 March 2006
by Tom Igoe
*/
int analogValue = 0; // Variable to hold the analog value.
void setup() {
// open the serial port at 9600 bit/s:
Serial.begin(9600);
}
void loop() {
// Read the analog input on pin 0:
analogValue = analogRead(0);
// Print it out in many formats:
Serial.println(analogValue); // print as an ASCII-encoded decimal
Serial.println(analogValue, DEC); // print as an ASCII-encoded decimal
Serial.println(analogValue, HEX); // print as an ASCII-encoded hexadecimal
Serial.println(analogValue, OCT); // print as an ASCII-encoded octal
Serial.println(analogValue, BIN); // print as an ASCII-encoded binary
Serial.println(analogValue, BYTE); // print as a raw byte value
// Delay 10 milliseconds before the next reading:
delay(10);
}
If your output is still gibberish, there's something wrong with your serial terminal.
The problem Here is analog device you might connected are not # same ground potentials.
Example: If your powering on Arduino board using PC and sensor is powered on using other source , But You trying to read value from Arduino port, for this instant it gives above error. Try this power on arduino and sensor from Same power source and try to read data using Serial Port through DOcklight you will get Problem solved.
You need to set the baud rate in the serial monitor window (bottom right corner) to the same value that has been set in your code (e.g. Serial.begin(9600);).
From what your output looks like, it seems like you need to convert valm into a string, so that you can print the value numerically.
Also, is the wire you plugged into analog in floating? Because if it is, it'll just act like an antenna and grab random noise (though, might have a strong 60Hz component).

Resources