I get this error with PlatortmIO
src\main.cpp: In function 'void loop()':
src\main.cpp:56:38: error: invalid conversion from 'const char*' to 'char*' [-fpermissive]
static char msg = str_out.c_str();
^
*** [.pio\build\esp01\src\main.cpp.o] Error 1
========================== [FAILED] Took 3.48 seconds ==========================/
433 MHz RF Module Transmitter BME280
*/
#include <RH_ASK.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme; // I2C
float hum; // Stores humidity value in percent
float temp; // Stores temperature value in Celcius
float press; // Stores pressor value
// Define output strings
String str_humid;
String str_temp;
String str_press;
String str_out;
// Create Amplitude Shift Keying Object
RH_ASK rf_driver;
void setup()
{
Serial.begin(9600);
Serial.println(F("BME280 test"));
bool status;
// Initialize ASK Object
rf_driver.init();
// Start BME Sensor
status = bme.begin(0x76);
if (!status)
{
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
}
void loop()
{
delay(2000); // Delay so sensor can stabalize
hum = bme.readHumidity(); // Get Humidity value
temp= bme.readTemperature(); // Get Temperature value
press= bme.readPressure(); //Get Pressoure
// Convert Humidity to string
str_humid = String(hum);
// Convert Temperature to string
str_temp = String(temp);
//Convert Pressessor
str_press = String (press);
// Combine Humidity and Temperature
str_out = str_humid + "," + str_temp + "," + str_press;
// Compose output character
static char *msg = str_out.c_str();
rf_driver.send((uint8_t *)msg, strlen(msg));
rf_driver.waitPacketSent();
}
String.c_str() return a const char* array, which is not compatible with your static char* msg.
Looking at your code, instead of converting float to String in order to use String concatenation, then convert to an array, it will be much simpler to just directly create a char array with sprintf().
hum = bme.readHumidity(); // Get Humidity value
temp= bme.readTemperature(); // Get Temperature value
press= bme.readPressure(); //Get Pressoure
char msg[50];
sprintf(msg, "%f,%f,%f", hum, temp, press);
String concatenation isn't safe in Arduino which has only 2k memory and should avoid whenever is possible, especially if you are new to Arduino programming and not familiar with how dynamic memory allocation works internally.
Related
I'm trying to get this Code for the AMT22 Encoder Using a ESP32C3-DevModule to work but the Arduino IDE is erroring me that "HSPI" is not declared in the scope any suggestions on what it should be declared as?
It also is Erroring for the line below
begin(_pinCLCK, _pinMISO, _pinMOSI, _pinSS);
but it should be pulling from the AMT22.h library those values.
#include "AMT22.h"
#include <stdlib.h>
#include <SPI.h>
SPIClass * AMT22::encoder = NULL; // this must be here -> see https://stackoverflow.com/questions/39336029/arduino-accessing-static-variable-in-the-classs-static-method
AMT22::AMT22(const byte CLCK,
const byte MISO,
const byte MOSI,
const byte SS) {
_pinCLCK = CLCK;
_pinMISO = MISO;
_pinMOSI = MOSI;
_pinSS = SS;
}
void AMT22::Begin() {
if (AMT22::encoder == NULL) {
AMT22::encoder = new SPIClass(HSPI);
AMT22::encoder -> setClockDivider(SPI_CLOCK_DIV32);
AMT22::encoder -> begin(_pinCLCK, _pinMISO, _pinMOSI, _pinSS); // SCLK, MISO, MOSI, SS
}
This is from the AMT22.h Library
private:
AMT22::Position getPositionSingle();
AMT22::Position getPositionMulti();
void setCSLine(uint8_t releaseLine);
uint8_t spiWriteRead(uint8_t sendByte, uint8_t releaseLine);
AMT22::Position position;
byte _pinMISO = 12;
byte _pinMOSI = 13;
byte _pinCLCK = 14;
byte _pinSS = 15;
// uninitalised pointers to SPI
objects
static SPIClass *encoder;
};
#endif
The code is intended to Get a Multiturn Function from the encoder- i.e. When the Motor spins the encoder will be able to serial print the amount of rotations counting upwards and downwards.
void loop() {
// put your main code here, to run repeatedly:
// send packet
p = (bme.readPressure() / 100.0F );
h = (bme.readHumidity());
t = (bme.readTemperature());
alt = bme.readAltitude(SEALEVELPRESSURE_HPA);
String data = String(h) + "-" + String(t)+ "-" + String(p)+ "-" + String(alt);
int dataLength = data.length(); dataLength++;
uint8_t total[dataLength]; //variable for data to send
data.toCharArray(total, dataLength); //change type data from string ke uint8_t
Serial.println(data);
rf95.send(total, dataLength); //send data
rf95.waitPacketSent();
delay(2000);
}
im using the radiohead library and it works really well on arduino to send the data and then receives on a esp32, but if i make the esp32 the sender with this code
it throws me this error
error: invalid conversion from 'uint8_t*' {aka 'unsigned char*'} to 'char*' [-fpermissive]
refer to toCharArray() function in arduino reference as they stated that :
myString.toCharArray(buf, len)
buf: the buffer to copy the characters into. Allowed data types: array of char.
so the function expects a parameter of type char* not uint8_t*
so either change :
uint8_t total[dataLength]; -> char total[dataLength];
or
data.toCharArray(total, dataLength); -> data.toCharArray((char*)total, dataLength);
either of them should solve your problem.
I'm facing a specific problem with SD card and Arduino. I want to create a function that creates a new file on the SD card for a different day. For now, I'm simulating calendar with ints. I know that problem was already discussed but I can't seem to find a similarly discussed problem.
Code:
#include <stdlib.h> // included for floatToString
#include <math.h>
#include <SPI.h>
#include <SD.h>
int year = 2014;
int month = 11;
int day = 4;
char dateTitle[20]; //= "0000000000.txt";
void printDateTitle(char* dateTitle, int Y, int M, int D){
//char dateTitle[20];
sprintf(dateTitle, "%4d-%02d-%02d.txt", Y, M, D);
return;
}
const int chipSelect = 4;
void setup() {
//printDateTitle(dateTitle, year, month, day);
Serial.begin(9600);
while (!Serial) {
;
}
Serial.print("Initializing SD card...");
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
while (1);
}
Serial.println("card initialized.");
}
void loop() {
Serial.print(dateTitle);
delay(1000);
File dataFile = SD.open(dateTitle, FILE_WRITE);
if (dataFile){
dataFile.println("something");
dataFile.close();
Serial.print(day);
Serial.println("something");
delay(1000);
} else
Serial.println("Error");
}
In the code, I have a function void printDateTitle that formats the inputs from the calendar to string which I want to use as a title for the file.
And also, when I define a function in the void loop() with printDateTitle(dateTitle, year, month, day); I get an "Error" in the output meaning SD.open = false.
The problem is that even though SD.open returns true it doesn't create a file on the SD card. .txt is included in the char array. I have also used capital .TXT.
I would be grateful for all the bits of advice regarding the problem.
For the reference, I'm using Arduino Uno and Micro SD card Adapter with Arduino IDE.
The Arduino SD Library documentation states that it uses the "short 8.3 names for files". Therefore only files with 8 characters as name and 3 for file extension are valid. For example: 12345678.txt is valid, 123456789.txt would be invalid.
Your date string (2014-11-04.txt) is to long because it has 10 characters instead of only 8.
Also make sure you've formatted the SD card to a FAT16 or FAT32 file system.
I'm using ArduinoJSON to write a couple of data points to my EEPROM on Arduino Uno. I'm running into a problem with getGroundedPR where I need to convert a uint8_t to a char to pass retrieved data into my JSON parser.
This is my first time using EEPROM so I'm willing to bet there's a better way to do this. Should I continue to use JSON or is there a better way? I'm being cautious of the 10k write limit (give or take) on the EEPROM.
the EEPROM read/write is commented out until I have my process nailed down
void IMUController::setGroundedPR(double p, double r) {
Serial.print("Setting IMU ground: ");
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["pitch"] = p;
root["roll"] = r;
root.printTo(Serial);
char buffer[256];
root.printTo(buffer, sizeof(buffer));
Serial.println();
// EEPROM.write(EEPROM_ADDRESS_IMU_GROUNDED, buffer);
}
double* IMUController::getGroundedPR() {
double ret[2] = {0, 0};
StaticJsonBuffer<200> jsonBuffer;
uint8_t json_saved = EEPROM.read(EEPROM_ADDRESS_IMU_GROUNDED);
char json[] = "asdf"; // convert json_saved to char here
JsonObject& root = jsonBuffer.parseObject(json);
if(!root.success()) {
// return the result
ret[0] = (double)root["pitch"];
ret[1] = (double)root["roll"];
return ret;
}
return ret;
}
The EEPROM functions read() and write() only deal with a single character. You need to use put() and get() to deal with arrays.
char buffer[256];
root.printTo(buffer, sizeof(buffer));
EEPROM.put(EEPROM_ADDRESS_IMU_GROUNDED, buffer);
And to read it back:
char json[256];
EEPROM.get(EEPROM_ADDRESS_IMU_GROUNDED, json);
JsonObject& root = jsonBuffer.parseObject(json);
You need to take care with he array sizes though, the EEPROM functions will get and put the number of bytes in the array (256). The string should be null terminated so the extra bytes shouldn't cause a problem.
I am taking voltage signal from Analog Input (A0 pin) and current signal (in the form of voltage) from Analog input (A1 pin), converting it to digital and then processing it to get Vrms, Irms and phase data. Then i am storing it in a "dataString" and writing it onto SD card.
The problem i am facing is that somewhere in the floating point computation of the power factor I am doing something wrong due to which the answer is being "displayed as" 1.00 whereas at an angle of 4.97 (degrees) i should get cos(4.97) = 0.9962 (Picture attached)
Image1
Although the program is using the correct value i.e., 0.9962 in further computations ( that of real Power) but i want it to display the power factor correctly upto 4 points after decimal. Here is my program code
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;
#include "DHT.h"
#define DHTPIN 8
#define DHTTYPE DHT21
DHT dht(DHTPIN, DHTTYPE);
#define count 100
const int analogInPin1 = A1;
const int analogInPin0 = A0;
const int chipSelect = 10;
void setup()
{
Serial.begin(115200);
Wire.begin();
RTC.begin();
if (! RTC.isrunning()) {
Serial.println("#RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
// uncomment it & upload to set the time, date and start run the RTC!
// RTC.adjust(DateTime(__DATE__, __TIME__));
}
analogReference(DEFAULT);
Serial.println("#DHTxx test!");
dht.begin();
Serial.print("#Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("#Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("#card initialized.");
Serial.println("#Date Time Vrms Irms Phase Power_factor Apparent_Power Real_Power Humidity Temperature");
}
void loop()
{
float sensorValue0[count];
float sumSensorValue0=0;
float meanSensorValue0=0;
float Vrms=0;
sumSensorValue0=0;
float sensorValue1[count];
float sumSensorValue1=0;
float meanSensorValue1=0;
float Irms=0;
int i=0;
sumSensorValue1=0;
DateTime now = RTC.now();
for(i=0;i<count;i++)
{
sensorValue1[i] = (analogRead(analogInPin1)*4.8)-3200; //4.8 mV (i.e. 0.0048 Volts) per unit.. Vref/1024.. here Vref = 5 V ....//3.220 V = Offset
sensorValue0[i] = (analogRead(analogInPin0)*4.8)-3200;
sensorValue1[i] = sensorValue1[i]*sensorValue1[i];
sensorValue0[i] = sensorValue0[i]*sensorValue0[i];
sumSensorValue1+= sensorValue1[i];
sumSensorValue0+= sensorValue0[i];
}
meanSensorValue1 = sumSensorValue1/count;
meanSensorValue0 = sumSensorValue0/count;
Irms = (sqrt(meanSensorValue1)*0.06); //60/1000 = 0.06 Calibrating 60 Ampere/1 Volt to give us the value for X amperes
Vrms = (sqrt(meanSensorValue0)*0.3565); // Multiplying with 356.5(the product of ratios of 9V and 12 V transformer) gives the measured voltage in mV.. dividing by 1000 to bring it to Volts from mV
float appPower;
appPower = Vrms*Irms;
float Vsense=0;
float LastVsense=0;
float Isense=0;
float LastIsense=0;
float phase;
float mean_phase=0;
float counter=0;
unsigned long timer;
for(int i=0;i<200;i++)
{
// put your main code here, to run repeatedly:
Isense=analogRead(A1)*4.8-3200;
Vsense=analogRead(A0)*4.8-3220;
if(Vsense>= 0 && LastVsense<0 && Isense<0 )
{
timer = micros();
do{
Isense=analogRead(A1)*4.8-3200;
}while(!(Isense>=0));
timer = micros()-timer;
phase = (timer*360.0)/20000.0;
mean_phase+=phase;
counter+=1.0;
}else;
if(Isense >= 0 && LastIsense < 0 && Vsense < 0 )
{
timer = micros();
do{
Vsense=analogRead(A0)*4.8-3200;
}while(!(Vsense>=0));
timer = micros()-timer;
phase = (timer*360.0)/20000.0;
mean_phase+=phase;
counter+=1.0;
}else;
LastIsense = Isense;
LastVsense = Vsense;
}
mean_phase= mean_phase/counter;
float realPower;
float powerFactor;
float phase_rad= mean_phase*PI/180.0;
powerFactor =cos(phase_rad); //phase converted to radian for cosine function
realPower = Vrms*Irms*powerFactor;
String dataString = "";
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(t) || isnan(h)) {
Serial.println("#Failed to read from DHT");
} else {
dataString+=now.year(), DEC;
dataString+="/";
dataString+=now.month(), DEC;
dataString+="/";
dataString+=now.day(), DEC;
dataString+=" ";
dataString+=now.hour(), DEC;
dataString+=":";
dataString+=now.minute(), DEC;
dataString+=":";
dataString+=now.second(), DEC;
dataString+=" ";
dataString+=Vrms;
dataString+=" ";
dataString+=Irms;
dataString+=" ";
dataString+=mean_phase;
dataString+=" ";
dataString+=powerFactor;
dataString+=" ";
dataString+=appPower;
dataString+=" ";
dataString+=realPower;
dataString+=" ";
dataString+=h;
dataString+=" ";
dataString+=t;
}
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
File dataFile = SD.open("datalog.dat", FILE_WRITE);
// if the file is available, write to it:
if (dataFile) {
dataFile.println(dataString);
dataFile.close();
// print to the serial port too:
Serial.println(dataString);
}
// if the file isn't open, pop up an error:
else {
Serial.println("#error opening datalog.dat");
}
delay(10000);
}
Although the program is using the correct value i.e., 0.9962 in further computations...
That points to the issue being in your printing code.
More specifically, I suspect that this line might be causing trouble:
dataString+=powerFactor;
You are using the String class, so WString.cpp is the relevant file.
If we inspect it, we find that on line 409 (at least, in my version of Arduino, 1.6.7 IIRC), the + operator is declared for floats, and it simply calls concat(float), which can be found on line 323:
unsigned char String::concat(float num)
{
char buf[20];
char* string = dtostrf(num, 4, 2, buf);
return concat(string, strlen(string));
}
If you read the dtostrf docs, you will find that this is converting a double (the float gets promoted) to a string with a width of 4 and 2 digits of precision.
The easiest way to get around this is to use dtostrf to convert the float to a string with the precision you want, and then append that string to your String instance.