I am trying to convert a string to a double in one of my Arduino projects (specifically using a Teensy 3.5 in the Arduino IDE) using Arduino's string.toDouble() command. When I try to implement the function as shown in the code below, I get the error:
<'class String' has no member named 'toDouble'>.
However, string.toFloat() and string.toInt() work successfully.
Any ideas as to what is going wrong?
String myNumberString = "100";
double myNumber = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
myNumber = myNumberString.toDouble()+1;
Serial.println(myNumber);
myNumberString = String(myNumber);
delay(1000);
}
The problem you are having is that arduino declares myNumberString as a String Object, so you can't use toDouble() to convert the string into a double because the function is not defined in the String class. You will have to use toFloat to convert your string. Here's the link I used to find this.
Seem like the Teensy's Arduino core is missing that function.
I only see toInt and toFloat inside Teensy's implementation of the String class. While the original Arduino core has it implemented.
Maybe you can use atof directly, like:
myNumber = atof(myNumberString.c_str());
Related
I'm new member here and also a joiner in programming
i try to extract information from my vehicle using OBD-II cable adapter. I try simple code to read the RPM and successfully got it and print it in serial monitor but i face a simple problem. Serial monitor display the PID-Code + current value of RPM as shown below:
010C849 where 010C: refer to RPM-PID used and 849: current value of RPM
so can i cutout the HEX number from the result and just display the value of RPM such as (849)
i used the following code:
Here is an example of the result `
#include <OBD2UART.h>
COBD obd;
void setup()
{
pinMode(13, OUTPUT);
obd.begin();
while (!obd.init());
}
void loop()
{
int value;
if (obd.readPID(PID_RPM, value)) {
Serial.println(value);
delay(1000);
}
}
`
You could use Regex, to cut out a pattern, but Arduino (and, in general, C++) does not provide support for regular expression parsing.
Once you have the string, you can use indexOf() and substring() to extract substrings. Once you have a substring, you can use toCharArray() to extract the character array, and atoi() to convert that to an integer.
Once you have integer values you can print them out.
I am having the same problem as described in this post on the Arduino forums. I have a slight deviation in that I am using an Arduino Leonardo, but otherwise the core problem is the same.
Trying to upload a sketch to my board results in Windows stating my 'USB device has malfunctioned and Windows does not recognize it'. The COM port used for the board then disappears, as with the post above.
I tried the solution posted by Louis Davis in the linked post, which allowed me to successfully reset the board and upload a known good sketch. When this is completed, the board is able to be recognised by Windows again, and the COM port reappears; the board can be used without issue.
I have two Leonardos and I have confirmed by replicating steps across both that it is my specific code which is causing the Windows error to appear, not down to a hardware issue.
Could anyone offer pointers on what in the below code is causing this? (Code is fully commented to describe purpose/methods used)
//Code including basic setup/loop and a function I created, asking for readings to be taken from 3 sensors
//when called, and to then assign the results to global variables
//The loop function should then print the global variables in question and wait for a while before repeating
//the process
#include <Wire.h> //using an I2C breakout (accelerometer)
#include "SparkFun_MMA8452Q.h" //accelerometer breakout's library
MMA8452Q accel; //create an instance of this accelerometer
int FSR_pin = A1; //force resistor pin
const int PHOTO_pin = A0; //phototransistor pin
//declare variables to use to take a base reading, to later measure against for changes
int base_PHOTO = 0;
int base_FSR = 0;
byte base_ORIEN = 0; //using the method recommended in the accelerometer's startup page to get orientation
//readings, which they say is passed back as a byte; section 'Reading Portrait/Landscape'
//on this page https://learn.sparkfun.com/tutorials/mma8452q-accelerometer-breakout-hookup-guide
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Wire.begin();
}
void baseReading() {
base_FSR = analogRead(FSR_pin);
base_PHOTO = analogRead(PHOTO_pin);
base_ORIEN = accel.readPL();
}
void loop() {
// put your main code here, to run repeatedly:
baseReading(); //call my own function to get base readings
Serial.println(base_FSR);
Serial.println(base_PHOTO);
Serial.println(base_ORIEN);
delay(5000);
}
int takeReading() {
}
I have taken readings from each sensor individually using test sketches from the component manufacturers; the problem only appeared when I tried to combine them into one bit of code. Here's a hyperlink to the accelerometer breakout guide referenced in the above code.
Solved: The code was missing the line accel.init(); from the setup function.
I first ruled out the FSR & phototransistor I was using, as running code for only these components performed as expected. That left the MMA8452Q's code to look at.
I'd been using the manufacturer's guide as linked above for the accelerometer, and Example #3 (orientation reading) from its library to write my code out; I managed to drop the init and assumed the problem was with the new .readPL method I had put in.
The example code uses .begin instead of .init, and also uses this as part of a print statement, so I didn't immediately catch on that the purpose of its inclusion was the same.
The fixed code is as follows:
//Code including basic setup/loop and a function I created, asking for readings to be taken from 3 sensors when called and assigned to global variables
//The loop function should then print the global variables in question and wait for a while before repeating the process
#include <Wire.h>
#include "SparkFun_MMA8452Q.h"
MMA8452Q accel;
int FSR_pin = A1;
const int PHOTO_pin = A0;
//variables to use to take a base reading, to later measure against for changes
int base_PHOTO = 0;
int base_FSR = 0;
byte base_ORIEN = 0;
void setup() {
Serial.begin(9600);
Wire.begin();
accel.init(); //The new line, which allows this to run as intended
}
void baseReading() {
base_FSR = analogRead(FSR_pin);
base_PHOTO = analogRead(PHOTO_pin);
base_ORIEN = accel.readPL();
}
void loop() {
baseReading();
Serial.println(base_FSR);
Serial.println(base_PHOTO);
Serial.println(base_ORIEN);
delay(5000);
}
I am writing a function:
void callFunctionAt(uint32_t address){
//There is a void at address, how do I run it?
}
This is in Atmel Studio's C++. If previous questions are to be believed, the simple answer is to write the line "address();". This cannot be correct. Without changing the header of this function, how would one call the function located at the address given?
The answer should be system-agnostic for all micro controllers which support standard c++ compilation.
The common way to do this is to give the argument the correct type. Then you can call it right away:
void callFunctionAt(void (*address)()) {
address();
}
However, since you wrote "Without changing the header of this function [...]", you need to cast the unsigned integer to a function pointer:
void callFunctionAt(uint32_t address) {
void (*f)() = reinterpret_cast<void (*f)()>(address);
f();
}
But this is not safe and not portabel because it assumes that the uint32_t can be casted into a function pointer. And this needs not to be true: "[...] system-agnostic for all micro controllers [...]". Function pointers can have other widths than 32 bits. Pointers in general might consist of more than the pure address, for example include a selector for memory spaces, depending on the system's architecture.
If you got the address from a linker script, you might have declared it like this:
extern const uint32_t ext_func;
And like to use it so:
callFunctionAt(ext_func);
But you can change the declaration into:
extern void ext_func();
And call it directly or indirectly:
ext_func();
callFunctionAt(&ext_func);
The definition in the linker can stay as it is, because the linker knows nothing about types.
There is no generic way. It depends on which compiler you are using. In the following I'll assume avr-g++ because it's common and freely available.
Spoiler: On AVR, it's more complicated than on most other machines.
Suppose you actually have a uint32_t address which would be a byte address. Function pointers in avr-g++ are word addresses actually, where a word has 16 bits. Hence, you'll have to divide the byte address by 2 first to get a word address; then cast it to a function pointer and call it:
#include <stdint.h>
typedef void (*func_t)(void);
void callFunctionAt (uint32_t byte_address)
{
func_t func = (func_t) (byte_address >> 1);
func();
}
If you started with a word address, then you can call it without further ado:
void callFunctionAt (uint32_t address)
{
((func_t) word_address)();
}
This will only work for devices with up to 128KiB of flash memory!
The reason is that addresses in avr-g++ are 16 bits long, cf. the layout of void* as per avr-gcc ABI. This means using scalar addresses on devices with flash > 128KiB will not work in general, for example when you issue callFunctionAt (0x30000) on an ATmega2560.
On such devices, the 16-bit address in Z register used by EICALL instruction is extended by the value held in the EIND special function register, and you must not change EIND after entering main. The avr-g++ documentation is clear about that.
The crucial point here is how you are getting the address. First, in order to call and pass it around properly, use a function pointer:
typedef void (*func_t)(void);
void callFunctionAt (func_t address)
{
address();
}
void func (void);
void call_func()
{
func_t addr = func;
callFunctionAt (addr);
}
I am using void argument in the declaration because this is how you'd do it in C.
Or, if you don't like the typedef:
void callFunctionAt (void (*address)(void))
{
address();
}
void func (void);
void call_func ()
{
void (*addr)(void) = func;
callFunctionAt (addr);
}
If you want to call a function at a specific word address like, for example 0x0 to "reset"1 the µC, you could
void call_0x0()
{
callFunctionAt ((func_t) 0x0);
}
but whether this works depends on where your vector table is located, or more specifically, how EIND was initialized by the startup code. What will always work is using a symbol and define it with -Wl,--defsym,func=0 when linking with the following code:
extern "C" void func();
void call_func ()
{
void (*addr)(void) = func;
callFunctionAt (addr);
}
The big difference compared to using 0x0 directly it that the compiler will wrap symbol func with symbol modifier gs which it will not do when using 0x0 directly:
_Z9call_funcv:
ldi r24,lo8(gs(func))
ldi r25,hi8(gs(func))
jmp _Z14callFunctionAtPFvvE
This is needed if the address is out of the scope of EIJMP to advise the linker to generate a stub.
1 This will not reset the hardware. The best approach to force a reset is by letting the watchdog timer (WDT) issue a reset for you.
Methods
Yet another situation is when you want the address of a non-static method of a class because you also need a this pointer in that case:
class A
{
int a = 1;
public:
int method1 () { return a += 1; }
int method2 () { return a += 2; }
};
void callFunctionAt (A *b, int (A::*f)())
{
A a;
(a.*f)();
(b->*f)();
}
void call_method ()
{
A a;
callFunctionAt (&a, &A::method1);
callFunctionAt (&a, &A::method2);
}
The 2nd argument of callFunctionAt specifies which method (of a given prototype) you want, but you also need an object (or pointer to one) to apply it. avr-g++ will use gs when taking the method's address (provided the following call(s) cannot be inlined), thus it will also work for all AVR devices.
Based on comments I think you are asking about how microcontroller calls function.
Could you compile your program to see assembly files?
I would recommend you to read one of them.
Every function after compiling are translated to instructions that CPU can do (loading to register, adding to register etc.).
So then your void foo(int x) {statements;} compile to simple CPU instructions and whenever you call foo(x) in your program, you are moving to instructions that are related to foo - you are calling a subroutine.
As far as I remeber there is a CALL function in AVR to invoke subroutines and the name of subroutine is the label where executing program jump and invoking next instruction at adress.
I think you can clarify your doubts when you read some AVR assembly tutorials.
It is fun (at least for me) to see what exactly CPU do when it calls function that I wrote, but it required to know what instructions do. You develop in AVR so there is a set of instructions that you can read about in this PDF and compare with your assembly files.
Recently, I've been writing an Arduino(Yún) sketch to get RGB values(0-255) from the bridge. I have Bridge.begin() in the setup and the following in the loop:
Bridge.get("r", r, 4);
Bridge.get("g", g, 4);
Bridge.get("b", b, 4);
Which should get the value from the bridge(1st argument) and set the local variable to it(2nd argument). The local variables r, g and b are defined with char r[4];(obviously each with the appropriate name). I understand all of this, however there is a problem:
The first Bridge.get() call always returns \u0001(Start of heading). I have solved this by adding a dummy bridge get to the beginning of the loop, however this seems weird to me because the first call returns the "Start of heading" in every loop.
Why is this and is there a better way to fix it?
EDIT:
The code is put to the bridge by a python script running on the Linux side of the Yún. The following is shortened because the code that works out the RGB values is fairly long, messy and shouldn't be part of the problem(famous last words :D).
#!/usr/bin/python
from sys import path
path.insert(0, '/usr/lib/python2.7/bridge')
from bridgeclient import BridgeClient
link = BridgeClient()
link.put("r", str(int(r)))
link.put("g", str(int(g)))
link.put("b", str(int(b)))
The arduino code(once again abridged) is as follows:
#include <Process.h>
char r[4];
char g[4];
char b[4];
void setup() {
Bridge.begin();
}
void loop() {
Process colo;
colo.runShellCommand("/mnt/sda1/colours.py");
while (colo.running());
Bridge.get("r", r, 4); //this command(whatever key it’s getting) always returns \u0001
Bridge.get("r", r, 4);
Bridge.get("g", g, 4);
Bridge.get("b", b, 4);
}
I have the below code to read a light sensor, convert to lux, concat with "lux." and send it to my SmartThings cloud.
Ultimately I want a value sent to SmartThings formatted like lux.110
void checkLux() {
float logLux = analogRead(lightPIN) * logRange / rawRange;
int luxValue = pow(10, logLux);
String statusUpdate = "lux." + luxValue;
Serial.println(statusUpdate);
smartthing.send(statusUpdate);
delay(1000);
}
This above code spits out some weird combination of characters to the serial monitor and doesnt print lux. or the luxvalue.
If I add this line String luxString = "lux."; and modify the line below, it all works great. Any thoughts on why I need to declare this string separately. According to the documentation either should work fine.
Also if there are any suggestions on variable savings within this block of code. I am not that great at it yet.
As Arduino just uses C++ most C++ functions will also work so dont just limit yourself to Arduino's reference pages.
Apparently the String constructor doesn't support numbers, you must convert them using the String() function first as seen here.
Alternatively I think you can append a string like this:
String statusUpdate = "lux.";
statusUpdate += luxValue;
as seen here,
which is the same as using String's concat function.
statusUpdate.concat(luxValue);