Invalid conversion from char to 'uint8_t' - arduino

I'm using a shift out statement to drive a few 7 seg displays (in the end)
but I'm running into a problem.
I have used #include <avr/pgmspace.h> libary as to save space for the processing.
At the end of it I need to shiftOut a binary number to be fed into a reg then to a BCD then to my display:
strcpy_P(buffer, (char*)pgm_read_word(&(Times[big])));
shiftOut(dataPin, clockPin, MSBFIRST, buffer);
in the buffer place will go the selected value (e.g. B00100011 should display 23),
my code gives me
Invalid conversion from char to 'uint8_t'
with the shiftOut line highlighted
Any ideas?

The problem here is that shiftOut expects a byte (uint8_t) as its 4th argument (value). The passed value is a char* (presumably declared as a prog_char array).
To fix this, the declaration of the value will need to use prog_uchar, like this:
prog_uchar values[] PROGMEM = { (prog_uchar) B00100011, ... };
...
int valueIndex = ...; // Index of value in the values array
shiftOut(dataPin, clockPin, MSBFIRST, pgm_read_byte(&(values[valueIndex])));

Related

Parsing char array to integer, atoi() returns squares

I'm using an android app to send values to control servos.
Code:
char inputData[4];
char buffer[3];
void loop()
{
if(Serial.available() > 3) {
for (int i = 0; i < 4; i++){
inputData[i] = Serial.read();
}
char buffer[4];
buffer[0] = inputData[1];
buffer[1] = inputData[2];
buffer[2] = inputData[3];
buffer[3] = '\0';
int angle = atoi(buffer);
Serial.write(angle);
}
}
Issue: I'm getting the values + A-F letters to address each servo - A10, A180, B30 etc. Now the trouble is turning this to an actual integer. As you can see I've declared a character array to store the integers in and as suggested in a post on the arduino forum, I added a \0 at the end of the array. Currently, the Atoi returns random characters, mostly squares and some random numbers. I've tried even assigning them to a string and then .toInt() but same issue there, mostly squares.
Any ideas?
Thanks!
Use print or println to see the number as text. write sends it as byte and Serial Monitor shows a symbol with that ASCII code.

Reading char sent from wireless transmitter and creating switch case

I'm trying to transmit a char wirelessly and have the receiver read that char through serial in order to create a switch statement.
When trying to convert into int, I get the same int value no matter what char I type into the html text box. Serial.print(buffer); is displaying the right char. All help appreciated.
This is the char I'm inputting, and the result in the serial
Let's try this way. After convert "buffer" from "char"-->"int".You can check if h is digital or not before doing something.
//..Your code..//
//..Your code..//
//..Your code..//
int h = (int)buffer;
if (isDigit(h))
{
//Do something;
}

Converting from void * to float

I have a pointer to some location in memory passed in, void *dataLoc.
Some program is transferring memory there as a bunch of unsigned chars where 0x00 is 0 and 0xFF is one.
I want to be able to pull, say, every 4th char and convert it to the float of what number is supposed to be represented. But I'm having trouble understanding how I get from a void * to an array of char[] to an array of float[].
My initial thought was to do something like
for(i=0,i<100,i++){
floatArray[i] = (float)(*((unsigned char *)dataLoc[4*i])) / 255;
}
the void * is cast to a char *.
the next 4th char is selected from the for loop
the * dereferences the char pointer, which should give me an unsigned char,
the float should change the char into a float, but a float representation of the number I want *255
I divide by 255 to get the fraction I want.
This fails, because I get the error "pointer of type 'void ' used in arithmetic
'void' is not a pointer-to-object type and beyond this, I'm not really confident that the rest of that line will work out the way I would like.
Can someone advise the proper way to handle this?
Good that you had warnings enabled.
dataLoc[4*i] occurs before (unsigned char *)dataLoc and leads to "pointer of type 'void *' used in arithmetic ..."
Cast to unsigned char * first.
Also remove extra level of *. The following is type unsigned char
((unsigned char *)dataLoc)[4*i]
Fixed:
void * dataLoc;
float floatArray[100];
// for(i=0,i<100,i++){ Use ';', not ','
for(int i=0;i<100;i++){
// Cast to `unsigned char *` before using `[]`
// * not needed here ---v
floatArray[i] = (float)( ( ((unsigned char *)dataLoc) [4*i])) / 255;
}
or
for (int i=0; i<100 ;i++) {
unsigned char value = ((unsigned char *)dataLoc)[4*i];
floatArray[i] = value / 255.0f;
}

Sending floats w/NRF8001

Using Blend Micro (basically Arduino Uno + Nordic nRF8001) to gather and send sensor data via BLE. Can't figure out how to send floats.
Here's a snip of code:
if ((lib_aci_is_pipe_available(&aci_state, PIPE_AIR_QUALITY_SENSOR_TEMPERATURE_MEASUREMENT_TX)) && (lib_aci_is_pipe_available(&aci_state, PIPE_AIR_QUALITY_SENSOR_RELATIVE_HUMIDITY_TX)) && (lib_aci_is_pipe_available(&aci_state, PIPE_AIR_QUALITY_SENSOR_CARBON_MONOXIDE_LEVEL_TX)))
{
// Read DHT & MQ7 sensors
h = dht.readHumidity(); // Read humidity from DHT
t = dht.readTemperature(); // Read temperature as Celsius from DHT
f = dht.readTemperature(true); // Read temperature as Fahrenheit from DHT
int VoutAn = analogRead(MQ7PIN); //Read Vout in analog from MQ7
// Compute heat index
hi = dht.computeHeatIndex(f, h);
// Compute CO in PPM
float Vout = (5.0/1023)*VoutAn;
co = 100.468*(pow(((5/Vout)-1),-1.43));
lib_aci_send_data(PIPE_AIR_QUALITY_SENSOR_TEMPERATURE_MEASUREMENT_TX, &f, sizeof(f));
lib_aci_send_data(PIPE_AIR_QUALITY_SENSOR_RELATIVE_HUMIDITY_TX, &h, sizeof(h));
lib_aci_send_data(PIPE_AIR_QUALITY_SENSOR_CARBON_MONOXIDE_LEVEL_TX, &co, sizeof(co));
}
And here's the compile error:
Arduino: 1.0.6 (Mac OS X), Board: "Blend Micro 3.3V/16MHz (overclock)"
BLE-DHT-MQ7-Test.ino: In function 'void loop()':
BLE-DHT-MQ7-Test.ino:287: error: cannot convert 'float*' to 'uint8_t*'
for argument '2' to 'bool lib_aci_send_data(uint8_t, uint8_t*,
uint8_t)'
BLE-DHT-MQ7-Test.ino:288: error: cannot convert 'float*' to 'uint8_t*'
for argument '2' to 'bool lib_aci_send_data(uint8_t, uint8_t*,
uint8_t)'
BLE-DHT-MQ7-Test.ino:289: error: cannot convert 'float*' to 'uint8_t*'
for argument '2' to 'bool lib_aci_send_data(uint8_t, uint8_t*,
uint8_t)'
My understanding of the aci_send_data function is that argument 2 is a uint8_t variable that points to the data in memory to be sent, and that this data can be in any form. But it only seems to work if the data is in a uint8_t variable - e.g. this compiles if I convert my variables to uint8_t - but I need floats...
So my questions:
Am I understanding the aci_send_data function correctly?
If so, what am I doing wrong?
If not, how can I send floats?
Thanks!
I am not sure about the parameters needed by lib_aci_send_data function however, according to this code it seems that the first parameter accepts the TX pin, the second one is the reference of the first byte (in a byte array) to be interpreted as a number, and the third is the length or number of bytes to consider.
The data type float is a 4-byte variable. If we have an array of bytes representing the float number, we can pass the reference of the first byte in the second parameter of the function, and pass 4 as the length (or number of bytes to consider) in the third parameter.
To convert float to byte array, see this thread. In your case, it would look like this:
typedef union _data {
float f;
char s[4];//since f takes 4 bytes
} myData;
myData q;
void setup(){
Serial.begin(9600);
}
void loop(){
q.f = 1.234;
//you can access the char array by using q.s
//q.s[0] q.s[1] ...
//take note that q.s is a reference to the first element
//so we can pass that immediately to the 2nd parameter
}
Now you can use the function in this way: lib_aci_send_data(PIPE_AIR_QUALITY_SENSOR_RELATIVE_HUMIDITY_TX, q.s, 4);
I cannot test this as of now since I'm on a different machine, please let me know if this was successful, I'm willing to add edits if necessary.
Thanks, it works! Seems a little cumbersome, but here's the code for getting all 3 variables I need to send as floats:
if ((lib_aci_is_pipe_available(&aci_state, PIPE_AIR_QUALITY_SENSOR_TEMPERATURE_MEASUREMENT_TX)) && (lib_aci_is_pipe_available(&aci_state, PIPE_AIR_QUALITY_SENSOR_RELATIVE_HUMIDITY_TX)) && (lib_aci_is_pipe_available(&aci_state, PIPE_AIR_QUALITY_SENSOR_CARBON_MONOXIDE_LEVEL_TX)))
{
typedef union _dataF
{
float f;
uint8_t fInt[4];
} myDataF;
myDataF F;
typedef union _dataH
{
float h;
uint8_t hInt[4];
} myDataH;
myDataH H;
typedef union _dataCO
{
float co;
uint8_t coInt[4];
} myDataCO;
myDataCO CO;
// Read DHT & MQ7 sensors
h = dht.readHumidity(); // Read humidity from DHT
t = dht.readTemperature(); // Read temperature as Celsius from DHT
f = dht.readTemperature(true); // Read temperature as Fahrenheit from DHT
int VoutAn = analogRead(MQ7PIN); //Read Vout in analog from MQ7
// Compute heat index
hi = dht.computeHeatIndex(f, h);
// Compute CO in PPM
float Vout = (5.0/1023)*VoutAn;
co = 100.468*(pow(((5/Vout)-1),-1.43));
F.f = f;
H.h = h;
CO.co = co;
lib_aci_send_data(PIPE_AIR_QUALITY_SENSOR_TEMPERATURE_MEASUREMENT_TX, F.fInt, 4);
lib_aci_send_data(PIPE_AIR_QUALITY_SENSOR_RELATIVE_HUMIDITY_TX, H.hInt, 4);
lib_aci_send_data(PIPE_AIR_QUALITY_SENSOR_CARBON_MONOXIDE_LEVEL_TX, CO.coInt, 4);
}
I put the sensor data into wider scope floats as I draw on them elsewhere in the program.

Storing a char in a char pointer

I have a global variable that is a *char. My main function header reads as int main(int argc, char* argv[argc]){...}. These two lines of code have to remain the way they are. The first argument of my main function is a number of type *char, that I convert to a char using atoi(...);. I am basically changing the ASCII value to its corresponding character. Now I want to store this local variable character I have into the global variable that is a char pointer. I know the problem is related to allocation of memory, but I am not sure how to go about this.
My code:
char* delim;
int main(int argc, char* argv[argc])
{
char delimCharacter;
if (isdigit(*(argv[3])) == 0) delim = argv[3]; //you can pass in a character or its ascii value
else { //if the argument is a number, then the ascii value is taken
delimCharacter = atoi((argv[3]));
printf("%s\t,%c,\n", argv[3], delimCharacter);
//sprintf( delim, "%c", delimCharacter ); // a failed attempt to do this
*delim = delimCharacter;
//strncpy(delim, delimCharacter, 1); // another failed attempt to do this
}
//printf("%s\n",delim);
This yields a seg fault.
You need to verify you have got (at least) 3 arguments before you start using them.
if (argc < 4)
{
printf("Need 3 args");
exit(1);
}
Then you need to allocate some memory to put the character in.
delim = malloc(2);
// TODO: Should check the result of malloc before using it.
*delim = delimCharacter;
delim[1] = 0; // Need to NULL terminate char*
You're dereferencing an uninitialized pointer. delim never gets initialized when it goes into the else block.
char delim[] = ","; // anything really, as long as as it's one character string
...
delim[0] = delimCharacter;
In addition to your memory issue, I think you are confused about what atoi does. It parses a string representation of a number and returns the equivalent int value, e.g. "10000" => 10,000. I think that you think it will give you the ASCII value of a character, e.g. "A" =>65.
Since you have a char *, and you are (I think) assuming that it contains a single character, you could simply do this:
delimCharacter = *(argv[3]);
However, there really seems to be no need to use the intermediate step of assigning this value to a char variable at all. If the end goal is to have delim point to the char that is the delimiter, then it seems this is all you need to do:
delim = argv[3];
Not only does this remove unnecessary code, but it means you would no longer need to allocate additional memory for delim to point to.
I would also declare delim as a const char * since I assume there is no reason to change it.

Resources