Converting Data Types from integer to char* - arduino

I am working on a school project that includes a list of i2C IDs that match particular sensors that I am using.
//DO, pH, Electric Conductivity, temperature
int channel_ids[] = {97, 99, 100, 102};
The problem is that I am trying to connect this to a particular API that uses different numbers to represent its channels and is a character pointer.
// where 70 is id for temperature for the API that I am trying to connect to.
char *GTAPI_ChannelID="70"
I want to create an IF statement that looks something like:
if (GTAPI_ChannelID == "70") {
channel_ids="102";
}
but I do not know how to do this when channel_ids is an integer and GTAPI_ChannelID is a character pointer.
Thanks

Related

How to transfer an Integer from an Arduino to another Arduino?

So I have to write a code that recognizes colour using a colour-detector.
The because the colourpalette is limited to just 6 colours I can be saved as an Integer (Red as 0, Green as 1 aso.).
Now I have problems transfering the Integer from the Arduino that handles the detector to the Arduino I have to write code on.
I tried using the analog (A0) pin but with that I only ended up with a 19-20 whenever I tried to transfer anything at all.
Is there a solution to transfer an Integer from 0-5?
Thanks in advance
Using the Analog is not a good solution. You should use the "Serial Connection". It only requires two cables - no other electronics - and the code is very simple (see below).
If you just want to transfer values in the range 0-255 or smaller (as in your case: 0-5), you can use the "byte"-type variable. One or multiple bytes can easily be transferred using a serial connection, using the "TX" (transmit) and "RX" (receive) pins of the Arduinos. You just connect the TX pin from Arduino #1 to the "RX" pin of Arduino #2 - and: connect the GND pins of the two.
In the setup code for both, you need to start the serial connection with the same baud rate, e.g.
void setup(){
Serial.begin(9600);
}
Arduino #1 is sending a byte using the following command:
byte color = 0; // declare the variable "color"
color = 3; // set the variable to any value in the range [0-255]
Serial.write(color); // transmit the byte-variable "color"
Arduino #2 is receiving the byte. Therefore it needs to continuously check for new serial data.
void loop() {
byte data = 0;
// - check for new serial data - and respond accordingly
if (Serial.available() > 0) {
int x = Serial.read(); // The "Serial.read" command returns integer-type
data = x; //
// - now: do something with "data"
if (data == 0) {
// "red" was received ... do something ...
} else if (data == 1) {
// "green" was received ... do something ...
} else if (data == 2) {
// ... and so on, and so on ...
}
}
// ... do other tasks
}
Make sure that in the "other tasks" you are not using the command "delay", as this would prevent your code from checking the serial for new data in a timely manner.
In exactly the same way, your Arduino #2 could also send data back to Arduino #1. In that case, you add one more cable connecting "TX" from #2 to "RX" of #1, and use the same code as above, on the respective other Arduino.
Serial is most universal, as you can test/simulate/use it by a broad variety of partners.
Here, you might code your possible values as human readable characters { '0' .. '5' } or
{'R', 'G', 'B', 'C', 'M', 'Y'} or whatever you like.
Eventually, I2C is a better way of serial communication.
Of course, an analog signal can be divided into 6 clearly distinguishable areas, if it's more about states than about events. You need electronics (low pass filter) to turn analogWrite PWM into analog constant values. And eventually, you have to handle the state transitions separately.
(Huh, sounds pretty complicated, doesn't it :) )

How to retrieve data size larger than Qt Modbus InputRegisters?

From what I understand, the range of QModbusDataUnit::InputRegisters is range 0-65535 which is unsigned short.
The method to read 1 unit of inputregisters is as follows:
QModbusDataUnit readUnit(QModbusDataUnit::InputRegisters, 40006, 1);
The value of that will be in the reply, i.e : int value = result.value(0);
My question is that what if I have to read a value of unsigned int which is much larger of the range of 0 to 4,294,967,295.
How can I retrieve that value?
As you stated, Modbus input registers are 16 bit unsigned integers. So without some type of conversion they are limited to the range: 0 - 65535. For 32-bit unsigned values it is typical (in Modbus) to combine two registers.
For example, the high 16-bits could be stored at 40006 and the low 16-bits at 40007.
So, if you were reading the value ‭2271560481‬ (0x87654321 hex), you would read ‭34661‬ (0x8765) from address 40006 and 17185 (0x4321 hex) from location 40007. You would then combine them to give you the actual value.
I don't know the Qt Modbus code, but expanding on your example code you can probably read both values at the same time by doing something like this:
readUnit(QModbusDataUnit::InputRegisters, 40006, 2);
and combine them
quint32 value = result.value(0);
value = (value << 16) | result.value(1);

My Qt app does not recieve all the data sent by arduino

I'll go right to the point. My arduino reads values from the adc port and send them via serial port(values from 0 to 255). I save them in a byte type vector. After sending an specific signal to arduino, it starts to send to Qt app the data saved in the vector. Everything is working except that the arduino should send 800 values and the app receives less values than that. If I set the serial baud rate to 9600, I get 220 values. If, instead, I set the baud rate to 115200, I get only 20 values. Can you guys help me to fix this? I would like to use 115200 baud rate, because I need a good trasmision speed at this project(Real time linear CCD). I'll leave some code below:
Arduino code:
void sendData(void)
{
int x;
for (x = 0; x < 800; ++x)
{
Serial.print(buffer[x]);
}
}
This is the function that sends the values. I think is enough information, so I summarized it. If you need more code, please let me know.
Qt serial port setting code:
...
// QDialog windows private variables and constants
QSerialPort serial;
QSerialPortInfo serialInfo;
QList<QSerialPortInfo> listaPuertos;
bool estadoPuerto;
bool dataAvailable;
const QSerialPort::BaudRate BAUDRATE = QSerialPort::Baud9600;
const QSerialPort::DataBits DATABITS = QSerialPort::Data8;
const QSerialPort::Parity PARITY = QSerialPort::NoParity;
const QSerialPort::StopBits STOPBITS = QSerialPort::OneStop;
const QSerialPort::FlowControl FLOWCONTROL = QSerialPort::NoFlowControl;
const int pixels = 800;
QVector<double> data;
unsigned int dataIndex;
QByteArray values;
double maximo;
...
// Signal and slot connection.
QObject::connect(&serial, SIGNAL(readyRead()), this,SLOT(fillDataBuffer()));
...
// Method called when there's data available to read at the serial port.
void Ventana::fillDataBuffer()
{
dataIndex++;
data.append(QString::fromStdString(serial.readAll().toStdString()).toDouble());
if(data.at(dataIndex-1) > maximo) maximo = data.at(dataIndex-1);
/* The following qDebug is the one I use to test the recieved values,
* where I check that values. */
qDebug() << data.at(dataIndex-1);
}
Thanks and sorry if it's not so clear, it has been an exhausting day :P
Ok... I see two probelms here:
Arduino side: you send your data in a decimal form (so x = 100 will be sent as 3 characters - 1, 0 and 0. You have no delimiter between your data, so how your receiver will know that it received value 100 not three values 1, 0 and 0? Please see my answer here for further explanation on how to send ADC data from Arduino.
QT side: There is no guarantee on the moment when readyRead() signal will be triggered. It may be immediately after first sample arrives, but it may be raised after there are already couple of samples inside the serial port buffer. If that happens, your method fillDataBuffer() may process string 12303402 instead of four separate strings 123, 0, 340 and 2, because between two buffer reads four samples arrived. The bigger the baudrate, the more samples will arrive between the reads, which is why you observe less values with a bigger baud rate.
Solution for both of your problems is to append some delimiting byte for your data, and split the string in the buffer on that delimiting byte. If you don't want to have maximum data throughput, you can just do
Serial.print(buffer[x]);
Serial.print('\n');
and then, split incoming string on \n character.
Thank you very much! I did what you said about my arduino program and after solving that, I was still not getting the entire amount of data. So the the problem was in Qt. How you perfectly explain, the serial buffer was accumulating the values too fast, so the slot function "fillDataBuffer()" was too slow to process the arriving data. I simplified that function:
void Ventana::fillDataBuffer()
{
dataIndex++;
buffer.append(serial.readAll());
}
After saving all the values in the QByteArray buffer, I process the data separately.
Thanks again man. Your answer was really helpful.

zigbee module callback function incompatible to ZCL spec

I have followed the ZCL report to implement the function which is able to receive the data sent from the sensor.
In the SDk, it is defined as the following:
void ZbZclReportFunc{
struct ZbZclClusterT * clusterPtr,
zbApsdeDataInt * dataIndPtr,
uint16_t attributeId,
const uint8_t * data
}
By implementing the callback function as shown above, I am able to receive all information except data.
In ZCL spec, the Temperature Measurement Cluster defines its "MeasuredValue" Signed 16-bit Integer.
I print out the data using the following format:
printf("Degree: 0x%04x", *data);
As I expect, the data shown is "0x002b" as an example.
By casting it to Signed 16-bit integer, it does not help.
printf("Degree: 0x%04x", (int16_t)*data);
Any idea?
Thanks
Zigbee packet data is little Endian. Also, the units for MeasuredValue are "hundredths of degrees Celsius". So if your measured temperature value was 26 degrees celsius, your data buffer would look like: 28 0A. To convert to celsius you would use:
double temperature = (double)((int16_t)(data[1] << 8) | (int16_t)data[0]) / 100.0;

Onewire temperatures to MQTT broker server

I am trying to modify the code from the example included in the onewire library for arduino so that no matter how many onewire devices I have plugged it will always find them and publish it to a MQTT using the device ID and the current temperature. I have gotten it to publish the temperature, but am having trouble adding the device ID or ROM which is in HEX to my topic.
So for example i want it to appear like this. Note the topic and msg for MQTT need to be Char* (more info here: http://knolleary.net/arduino-client-for-mqtt/api/#publish1)
topic = Celsius eg 12.09
payload (or msg) = \home[ROM]\temperature\current eg. \home\2894AA6220025\temperature\current
(just an example of the output you normally get when you run the code without my additions, this is the serial output!! notice the ROM and celsius that I want to use)
Have put my full code here, it is just a modification of the included onewire example with the pubsub MQTT part added on.
(see line 155 onwards) https://gist.github.com/matbor/5931466
//publish the temp now to mqtt topic
String strTopic = "/house/285A9282300F1/temperature/current"; // need to replace the 285A9282300F1 with the ROM ID on each LOOP!
char charMsg[10];
String strMsg = dtostrf(celsius, 4, 2, charMsg); //convert celsius to char
char charTopic[strTopic.length() + 1];
//char charMsg[strMsg.length() + 1];
strTopic.toCharArray(charTopic, sizeof(charTopic));
strMsg.toCharArray(charMsg, sizeof(charMsg));
client.publish(charTopic,charMsg);
Add this to the top of your sketch, outside of the loop function:
char hexChars[] = "0123456789ABCDEF";
#define HEX_MSB(v) hexChars[(v & 0xf0) >> 4]
#define HEX_LSB(v) hexChars[v & 0x0f]
This defines a pair of macros that return the most-significant and least-significant bytes of an int as the appropriate HEX character. (There may be more appropriate built-in's for this, but this is what I use out of habit).
The following code will insert the ROM, as a HEX string, into the topic. Note you can create the topic as a char[] directly - you don't need to go via a String object.
char charTopic[] = "/house/XXXXXXXXXXXXXXXX/temperature/current";
for (i = 0; i < 8; i++) {
charTopic[7+i*2] = HEX_MSB(addr[i]);
charTopic[8+i*2] = HEX_LSB(addr[i]);
}
For the payload, I'm not sure if it is 100% necessary, but I always explicitly initialise any char[] to all 0's when using as a buffer. This ensures whatever is written into the buffer will definitely be null-terminated. Again, you don't need to go via String types:
char charMsg[10];
memset(charMsg,'\0',10);
dtostrf(celsius, 4, 2, charMsg);
Finally, publish the message:
client.publish(charTopic,charMsg);

Categories

Resources