Overloading function handling char and String - arduino

I'm making a function to handle a message, then print the message using Serial.println(). I have it working, but ran into an issue I can't explain. The first sample code below works, the second (swapping the order of my function declaration) will compile and load, but causes the Teensy 4.1 to crash. I'm using PlatformIO on VSCode.
Can anyone tell me what is wrong with the second code, and why it will compile without error, but not run?
This works:
#include <Arduino.h>
void LogMsg(const char *msg){
Serial.println(msg);
}
void LogMsg(String s){ LogMsg(s.c_str()); }
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("reset");
}
void loop() {
// put your main code here, to run repeatedly:
String str3 = "testing string cat ";
uint32_t var = 12345;
LogMsg(str3 + var);
delay(500);
}
This compiles, loads, but crashes, causing continuous resets:
#include <Arduino.h>
void LogMsg(String s){ LogMsg(s.c_str()); } // <-- swapped order
void LogMsg(const char *msg){ // <-- swapped order
Serial.println(msg);
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("reset");
}
void loop() {
// put your main code here, to run repeatedly:
String str3 = "testing string cat ";
uint32_t var = 12345;
LogMsg(str3 + var);
delay(500);
}
Edit: The definition of void LogMsg(String s) was changed to reflect error in original and the simplification suggested by #hcheung. Behavior remains the same. The first instance works, the second crashes.

C strings are terminated with '\0'. So toCharArray() will append a null character to your Ardunio String. Otherwise you would have to provide a length with the char pointer everytime you want to use that string.
Your char array must be big enough to fit this extra character or you will cause an access violation if toCharArray does not throw an exception first.

Related

Converting char starting with "0b" or "0B" to unsigned long

I am working on a project for a client so I am given a lot of code I cannot modify. I am stuff in a weird situation because of this problem. Nonetheless, I have a char with 34 indexes that I need to convert into an unsigned long type. I have seen numerous methods to accomplish this such as strtout, atol, etc. None have worked because the string starts with "0b" (ie "0b10000010000010000010000010000000"). Without the "0b", the rest of the code will not function properly. I tested with varying beginning 2 chars but nothing has led to a successful trial. Is there a function or code available that can convert the previously mentioned string into unsigned long? Any help is greatly appreciated.
You can combine the fact that a character - '0' is the number of that digit and use bit shifting to build the number up from the string:
unsigned long binaryToUL(String numberString){
int i;
unsigned long answer = 0;
if(numberString.startsWith("0b"))
for(i = 2; i<numberString.length(); i++)
answer = (answer << 1) + (numberString[i] - '0');
return answer;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
unsigned long test;
String testString = "0b10000010000010000010000010000000";
test = binaryToUL(testString);
Serial.println(testString);
Serial.println(test,BIN);
Serial.println(test);
while(true)
;
}
To convert a string a string representation of a binary that started with a "0b" or "0B", you need to remove the header first, then convert to the an unsigned long (uint32_t). Depend on what is the original string type (char[], char*) but an Arduino String in this case would make it easier to work with.
String myStr = "0b10000010000010000010000010000000";
void setup(){
Serial.begin(115200);
myStr.toUpperCase();
myStr.replace("0B", "");
uint32_t ul = strtoul(myStr.c_str(), NULL, 2);
Serial.println(ul, BIN);
}
void loop(){
}

Calling void function arduino

I have written the following code:
void dice (int &x) {
for (int i = 0;i<7;i++){
delay (35);
int kocka;
kocka = random (1,7);
randomSeed (analogRead (A7));
delay(5);
}
}
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println(dice(int x));
};
However when I try to compile it, I get this error:
expected primary-expression before 'int'
You can call a void function, but for the argument you pass you don't put "int". You know this if you think about it, when you write a digitalWrite do you put "int" in front of the pin number? You only need the int when you are writing the function prototype.
You also don't have any variable x defined to pass to that function, so your next error is "x not declared in this scope" since in the loop function there is no x variable.
You have another problem lurking next. Your function is defined to return void. That means it returns nothing. And sure enough, there is no return statement. So when you remove the "int" in the Serial.print line, and define a variable x, you will get a "void value not ignored" error. You can't print the return value from a function that has no return value.
It isn't really clear what you want that to print out. Edit your question to say what you want to happen and maybe someone can help you figure out how to do it.

How to convert string to int in processing

I am trying to make a hands free mouse using Arduino IDE and Processing IDE. I don't have a problem with serializing the code and converting to string, but when I try and convert the serial string into int the int goes to 0. I have tried to trim it and used integer.parseInt but it still gives me the error:
NumberFormatException : For input String:"".
Here is my code:
import processing.serial.*;
import java.awt.event.KeyListener;
import java.awt.Robot;
Serial myPort; // Create object from Serial class
Robot robot;
String val; // Data received from the serial port
boolean valtrue;
int xy = 0;
int x=0;
void setup()
{
String portName = Serial.list()[3];
myPort = new Serial(this, portName, 9600);
myPort.bufferUntil('.');
try {
robot = new Robot();
}
catch (Exception e) {
e.printStackTrace();
}
}
void draw() {
//reading serial port until \n
String sensorValue = myPort.readStringUntil('\n');
if (sensorValue != null) {
int value = Integer.parseInt(sensorValue.trim());
println(value);
}
}
If anyone is able to help, please answer.
Processing has an int() function that you can use instead of Integer.parseInt(). Behind the scenes the int() function is calling the Integer.parseInt() function, but it's shorter. Up to you.
But your error says it all: you're passing an empty String value "" into the parseInt() function. An empty String value can't be turned into a number, so you get the exception.
You're going to have to track down why your String value is empty, but that's what's causing this particular error. I will point out that the draw() function is called 60 times per second, and you're trying to read from your port every single time, so maybe you're reading faster than you're writing?

Arduino error: does not name a type?

I have written a library, but have problem with error does not name a type. I've tryed everything, searched for couple of hours and no luck. Library is placed in the "libraries" folder of the arduino sketch folder. Please help!!! I am using OSX, but the same problem occurs on Windows also.
This is header file of the library:
#ifndef OpticalSensor_h
#define OpticalSensor_h
#include <Arduino.h>
#include <SD.h>
#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>
#include <String.h>
class OpticalSensor
{
public:
OpticalSensor(int analogPort);
void LCDInit(int columns, int rows);
void SerialInit(int bitRate);
void SDInit();
double& ReadFromAnalogPort();
void SDCreateFile(String fileName);
void SDDeleteFile(String fileName);
void SDWriteToFile(String fileName);
void SDStreamToFile(String Text);
void SDOpenFileToStream(String fileName);
private:
int _analogPort;
bool _displayFlag;
Adafruit_RGBLCDShield _lcd;
File _MainRecFile;
double _voltage;
void _LCDClearAll();
void _LCDWriteInTwoRows(String row1, String row2);
void _DelayAndClearLCD(bool returnStatus);
};
#endif
This is .cpp file of the library:
#include <OpticalSensor.h>
Adafruit_RGBLCDShield _lcd;
File _MainRecFile;
double _voltage;
OpticalSensor::OpticalSensor(int analogPort)
{
_analogPort = analogPort;
}
void OpticalSensor::LCDInit(int columns, int rows)
{
_lcd = Adafruit_RGBLCDShield();
_lcd.begin(columns,rows);
}
void OpticalSensor::SerialInit(int bitRate)
{
Serial.begin(bitRate);
_bitRate = bitRate;
while(!Serial) {
//wait until serial is not open
}
}
void OpticalSensor::SDInit()
{
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
pinMode(10, OUTPUT);
//check if SD can be found and initialized. Print also message to
//Serial if initialized and to _lcd if initialized.
if(!SD.begin(4)) {
if(Serial){
Serial.println("Initialization failed!");
}
if(_lcd){
_lcd.print("Init failed!");
}
_DelayAndClearLCD(true);
}
else {
if(Serial) {
Serial.println("Initialization done!");
}
if(_lcd) {
lcd.print("Init done!");
}
_DelayAndClearLCD(false);
}
}
void OpticalSensor::SDCreateFile(String fileName)
{
//check if file allready exists, if not it creates one
//and writes apropriate response to
//lcd and Serial if they are initialized.
if(SD.exists(fileName)) {
if(Serial) {
Serial.println(fileName + " already exists!");
}
if(_lcd) {
_LCDWriteInTwoLines(fileName,"already exists!");
}
_DelayAndClearLCD(false);
}
else
{
if(Serial) {
Serial.println(fileName + "Creating file " + fileName + "...");
}
if(_lcd) {
_LCDWriteInTwoLines("Creating file", fileName);
}
_MainRecFile = SD.open(fileName + ".txt", FILE_WRITE);
_MainRecFile.close();
_DelayAndClearLCD(false);
//check if file was created successffully and print apropriate response
//to lcd and Serial if they are initialized
if(SD.exists(fileName + ".txt")) {
if(Serial) {
Serial.println(fileName + ".txt" + " created successffully!");
}
if(_lcd) {
_LCDWriteInTwoLines(fileName + ".txt", "created!");
}
_DelayAndClearLCD(false);
}
else {
if(Serial) {
Serial.println("error: failed to create file!");
}
if(_lcd) {
_LCDWriteInTwoLines("error: failed to","create file!");
}
_DelayAndClearLCD(false);
}
}
}
//delete file from SD card
void OpticalSensor::SDDeleteFile(String fileName)
{
}
//open file, write data to it, and close file after.
void OpticalSensor::SDWriteToFile(String fileName, String Text)
{
_MainRecFile = SD.open(fileName + ".txt", FILE_WRITE);
_MainRecFile.println(Text);
_MainRecFile.close();
}
//Open file to stream data to it.
void OpticalSensor::SDOpenFileToStream(String fileName)
{
_MainRecFile = SD.open(fileName + ".txt", FILE_WRITE);
}
//Write data to file while file is open.
//Notice that you can stream data only to one file at a time!!!
//For instance, if you have two sensors that you want to
//write data to two different files, you have to use SDWriteToFile
//function!!!
void OpticalSensor::SDStreamToFile(String Text)
{
if(_MainRecFile) {
_MainRecFile.println(Text);
}
}
//close file that you streamed data too.
void OpticalSensor::SDCloseStreaming(String fileName)
{
_MainRecFile.close();
}
//clear entire LCD
void OpticalSensor::_LCDClearAll()
{
_lcd.clear();
_lcd.setCursor(0,0);
}
void OpticalSensor::_LCDWriteInTwoRows(String row1, String row2)
{
//write first String in row1
_lcd.print(row1);
//set cursor to the beginning of row 2
_lcd.setCursor(0,1);
//write second String to row 2
_lcd.print(row2);
}
void OpticalSensor::_DelayAndClearLCD(bool returnStatus)
{
//if Serial or _lcd are initialized, delay for 2 seconds
//and clear LCD
if(Serial || _lcd) {
delay(2000);
if(_lcd)
_LCDClearAll();
}
//terminate
if(bool == true) {
return;
}
}
double& ReadFromAnalogPort()
{
_voltage = analogRead(_analogPort);
return _voltage;
}
And this is the .ino file where library is included:
#include <OpticalSensor.h>
OpticalSensor sensor(0);
void setup() {
sensor.LCDInit(16,2);
sensor.SerialInit(9600);
sensor.SDInit();
sensor.SDCreateFile("test1");
sensor.SDOpenFileToStream("test1");
}
void loop() {
}
this is the error:
In file included from Test_OpticalSensorLib.ino:1:
/Users/gaspersladic/Documents/Arduino/libraries/OpticalSensor/OpticalSensor.h:34:
error: 'Adafruit_RGBLCDShield' does not name a type
/Users/gaspersladic/Documents/Arduino/libraries/OpticalSensor/OpticalSensor.h:35:
error: 'File' does not name a type
The two includes you mention in your comment are essential. 'does not name a type' just means there is no definition for that identifier visible to the compiler. If there are errors in the LCD library you mention, then those need to be addressed - omitting the #include will definitely not fix it!
Two notes from experience which might be helpful:
You need to add all #include's to the main sketch - irrespective of whether they are included via another #include.
If you add files to the library folder, the Arduino IDE must be restarted before those new files will be visible.
I got the does not name a type error when installing the NeoMatrix library.
Solution: the .cpp and .h files need to be in the top folder when you copy it, e.g:
myArduinoFolder/libraries/Adafruit_NeoMatrix/Adafruit_NeoMatrix.cpp
When I used the default Windows unzip program, it nested the contents inside another folder:
myArduinoFolder/libraries/Adafruit_NeoMatrix/Adafruit_NeoMatrix/Adafruit_NeoMatrix.cpp
I moved the files up, so it was:
myArduinoFolder/libraries/Adafruit_NeoMatrix/Adafruit_NeoMatrix.cpp
This fixed the does not name a type problem.
I found the solution to this problem in a "}". I did some changes to my sketch and forgot to check for "}" and I had an extra one. As soon as I deleted it and compiled everything was fine.
Don't know it this is your problem but it was mine.
Void setup() does not name a type
BUT
void setup() is ok.
I found that the sketch I copied for another project was full of 'wrong case' letters. Onc efixed, it ran smoothly.emphasized text
The only thing you have to do is adding this line to
your sketch
#include <SPI.h>
before #include <Adafruit_MAX31855.h>.
More recently, I have found that other factors will also cause this error. I had an AES.h, AES.cpp containing a AES class and it gave this same unhelpful error. Only when I renamed to Encryption.h, Encryption.cpp and Encryption as the class name did it suddenly start working. There were no other code changes.
My code was out of void setup() or void loop() in Arduino.
Usually Header file syntax start with capital letter.I found that code written all in smaller letter
#ifndef DIAG_H
#define DIAG_H
#endif

Arduino: Putting servos in my class causes them to rotate all the way to one side

I am trying to create a new class that controls two servos.
My code compiles just fine. However, when I run it, the servos just turn all the way to one direction. This seems to happen when I try instantiating the class (when in the constructor, I attach the servos in the class to pins).
In My class's header file, I have
[UPDATED]
#ifndef ServoController_h
#define ServoController_h
#include "Arduino.h"
#include <Servo.h>
class ServoController
{
public:
ServoController(int rotateServoPin, int elevateServoPin);
void rotate(int degrees);
void elevate(int degrees);
private:
Servo rotateServo;
Servo elevateServo;
int elevationAngle;
int azimuthAngle;
};
#endif
Code so far for my Class:
#include "Arduino.h"
#include "ServoController.h"
ServoController::ServoController(int rotateServoPin, int elevateServoPin)
{
azimuthAngle = 0;
elevationAngle = 0;
elevateServo.attach(elevateServoPin);
rotateServo.attach(rotateServoPin);
}
void ServoController::rotate(int degrees)
{
//TO DO
rotateServo.write(degrees);
}
void ServoController::elevate(int degrees)
{
//TO DO
elevateServo.write(degrees);
}
And finally my arduino sketch so far is just:
#include <ServoController.h>
#include <Servo.h>
ServoController sc(2 , 3);
void setup()
{
}
void loop()
{
}
I'm pretty sure the circuit I am using is fine, since if I do not use my class, and just use the servo library directly in my arduino file, the servos move correctly.
any ideas why this might happen?
[UPDATE]
I actually got this working. In my constructor, I have removed the lines to attach the servos to pins. Instead, I have added another method to my class which does the attachment.
ServoController::ServoController(int rotateServoPin, int elevateServoPin)
{
azimuthAngle = 0;
elevationAngle = 0;
// elevateServo.attach(elevateServoPin);
// rotateServo.attach(rotateServoPin);
}
void ServoController::attachPins(int rotateServoPin, int elevateServoPin)
{
azimuthAngle = 0;
elevationAngle = 0;
elevateServo.attach(elevateServoPin);
rotateServo.attach(rotateServoPin);
}
I then call this in my sketch's setup() function:
void setup()
{
sc.attachPins(2,3);
}
It seems like if I attach my servos outside of the setup() function, my problem occurs.
[UPDATE July 27 9:13PM]
Verified something with another test:
I created a new sketch where I attached a servo before setup():
#include <Servo.h>
Servo servo0;
servo0.attach(2);
void setup()
{
}
void loop() // this function runs repeatedly after setup() finishes
{
servo0.write(90);
delay(2000);
servo0.write(135);
delay(2000);
servo0.write(45);
delay(2000);
}
When I try to compile, Arduino throws an error:
"testservotest:4: error: expected constructor, destructor, or type conversion before '.' token"
So there was an error, but it was not thrown when the attach method was called from a class
Thanks very much
The call to servo0.attach() needs to be inside the setup routine:
#include <Servo.h>
Servo servo0;
void setup(){
servo0.attach(2);
}
As you discovered with your attachServo routine. You don't need the extra routine, just call attach method inside the setup.
If what you want it in a class, you will have to have a method in the class to do the pin assignment, and call this method either in setup() (one time assignment) or in loop() (dynamic assignment during program execution).
Pin assignment cannot be done in the constructor of a global variable when using the Servo.h library as the timer used to manage the servo output get corrupted between the time you create the object and the time setup() is executed.

Resources