I have a serial port application which is written C++/CLI
To read data from the ports input buffer I am using
String^ inputString = System::IO:Ports::SerialPort::ReadExisting();
I need to convert the inputString value to an array of bytes. I have tried using
array<Byte> ^unicodeBytes = System::Text::Encoding::Unicode->GetBytes( inputString );
This works so long as the value being read in to my port input buffer is less than 0x7F (hex). Any values greater than 0x7F gets converted to 0x3F = "?"
E.g. if I send two bytes comprising {0x7F, 0xFF} to my input port then when I read and convert them the array unicodeBytes = { 0x7F 0x00, 0x3F 0x00} when looked at in the debugger watch window of VS2008
According to the unicode tables I have looked at OxFF is a valid unicode value equal to a latin small letter 'y' with two small dots above it.
Any suggestins on how to convert 'y' with two samll dots = 0xFF in string format to 0xFF in a byte array would be greatly appreciated.
Use the SerialPort's Read method to get bytes instead of decoding encoded text:
int BufferSize = <some size>;
array<byte> ^bytes = gcnew array<byte>(BufferSize);
int available = serialPort->BytesAvailable;
serialPort->Read(bytes, 0, Math::Min(available, BufferSize));
Related
I send 3 set of data from 3 sensors from Arduino 1 (router) to another Arduino(coordinator) to with wireless technology (xbee):
On coordinator, I receive wireless data from this 3 sensors(from the router) perfectly. The data stream is something like this(each sensor data on its line):
22.5624728451
944
8523
I want to have these 3 values as 3 variables that get updated constantly and then pass these values on to the rest of the program to make something like print on LCD or something else:
temperature=22. 5624728451
gas=944
smoke=8523
Initially, I had only 2 sensors and I send the data of these 2 sensors something like this:
22.5624728451944(22.5624728451 – temperature, 944 - gas) and I received both of them on the same line and divided everything into two variables(with readString.substring() ) with the code below. But now I have 3 sensors and I receive data on a separate line because I don't know which is the length of each data string … And I can't use the same technique (sending only one string that contain all sensor data on the same line and then divide them)
My old code:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12,11,10,9,8,7);
String temperature;
String gas;
String readString;
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
}
void loop() {
while (Serial.available() > 0)
{
char IncomingData = Serial.read();
readString += IncomingData ;
temperature = readString.substring(0, 13); //get the first 13 characters
gas = readString.substring(13, 16); //get the last 3 characters
Serial.print(IncomingData); //here I have my string: 20.1324325452924 wichs is updating properly when I have sensor values changes
// Process message when new line character is DatePrimite
if (IncomingData == '\n')
{
Serial.println(temperature);
lcd.setCursor(0,0);
lcd.write("T:");
lcd.print(temperature);
delay(500);
temperature = ""; // Clear DatePrimite buffer
Serial.println(gaz);
lcd.begin(16, 2);
lcd.setCursor(0,1);
lcd.write("G:");
lcd.print(gas);
delay(500);
gaz = ""; // Clear DatePrimite buffer
readString = "";
}
}
}
All I want to do now is to assign a variable for every sensor data (3 lines – 3 variables for each line) updated constantly and then pass these values on to the rest of the program. Does anyone have any idea how to modify the code tO work in this situation?
Thank you in advance!
I would recommend that you concatenate the values into the same line on the sending end and use a delimiter like a comma along with string.split() on the receiving end if you are committed to using string values. EDIT: It appears Arduino does not have the string.split() function. See this conversation for an example.
An alternative would be to set a standard byte length and send the numbers as binary instead of ASCII encoded strings representing numbers. See this post on the Arudino forum for a little background. I am recommending sending the number in raw byte notation rather than as ASCII characters. When you define a variable as in integer on the arduino it defaults to 16-bit signed integer value. A float is a 32-bit floating point number. If, for example, you send a float and two ints as binary values the float will always be the first 4 bytes, the first int, the next 2 and the last int the last 2. The order of the bytes (endianness, or most significant byte first (Big Endian, Motorolla style)/least significant bit first (Little Endian, Intel style)).
I have an application that playback audio. It takes encoded audio data over RTP and decode it to 16bit array. The decoded 16bit array is converted to 8 bit array (byte array) as this is required for some other functionality.
Even though audio playback is working it is breaking continuously and very hard to recognise audio output. If I listen carefully I can tell it is playing the correct audio.
I suspect this is due to the fact I convert 16 bit data stream into a byte array and use the write(byte[], int, int, AudioTrack.WRITE_NON_BLOCKING) of AudioTrack class for audio playback.
Therefore I converted the byte array back to a short array and used write(short[], int, int, AudioTrack.WRITE_NON_BLOCKING) method to see if it could resolve the problem.
However now there is no audio sound at all. In the debug output I can see the short array has data.
What could be the reason?
Here is the AUdioTrak initialization
sampleRate =AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
minimumBufferSize = AudioTrack.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
minimumBufferSize,
AudioTrack.MODE_STREAM);
Here is the code converts short array to byte array
for (int i=0;i<internalBuffer.length;i++){
bufferIndex = i*2;
buffer[bufferIndex] = shortToByte(internalBuffer[i])[0];
buffer[bufferIndex+1] = shortToByte(internalBuffer[i])[1];
}
Here is the method that converts byte array to short array.
public short[] getShortAudioBuffer(byte[] b){
short audioBuffer[] = null;
int index = 0;
int audioSize = 0;
ByteBuffer byteBuffer = ByteBuffer.allocate(2);
if ((b ==null) && (b.length<2)){
return null;
}else{
audioSize = (b.length - (b.length%2));
audioBuffer = new short[audioSize/2];
}
if ((audioSize/2) < 2)
return null;
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
for(int i=0;i<audioSize/2;i++){
index = i*2;
byteBuffer.put(b[index]);
byteBuffer.put(b[index+1]);
audioBuffer[i] = byteBuffer.getShort(0);
byteBuffer.clear();
System.out.print(Integer.toHexString(audioBuffer[i]) + " ");
}
System.out.println();
return audioBuffer;
}
Audio is decoded using opus library and the configuration is as follows;
opus_decoder_ctl(dec,OPUS_SET_APPLICATION(OPUS_APPLICATION_AUDIO));
opus_decoder_ctl(dec,OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC));
opus_decoder_ctl(dec,OPUS_SET_FORCE_CHANNELS(OPUS_AUTO));
opus_decoder_ctl(dec,OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
opus_decoder_ctl(dec,OPUS_SET_PACKET_LOSS_PERC(0));
opus_decoder_ctl(dec,OPUS_SET_COMPLEXITY(10)); // highest complexity
opus_decoder_ctl(dec,OPUS_SET_LSB_DEPTH(16)); // 16bit = two byte samples
opus_decoder_ctl(dec,OPUS_SET_DTX(0)); // default - not using discontinuous transmission
opus_decoder_ctl(dec,OPUS_SET_VBR(1)); // use variable bit rate
opus_decoder_ctl(dec,OPUS_SET_VBR_CONSTRAINT(0)); // unconstrained
opus_decoder_ctl(dec,OPUS_SET_INBAND_FEC(0)); // no forward error correction
Let's assume you have a short[] array which contains the 16-bit one channel data to be played.
Then each sample is a value between -32768 and 32767 which represents the signal amplitude at the exact moment. And 0 value represents a middle point (no signal). This array can be passed to the audio track with ENCODING_PCM_16BIT format encoding.
But things are going weird when playing ENCODING_PCM_8BIT is used (See AudioFormat)
In this case each sample encoded by one byte. But each byte is unsigned. That means, it's value is between 0 and 255, while 128 represents the middle point.
Java has no unsigned byte format. Byte format is signed. I.e. values -128...-1 will represent actual values of 128...255. So you have to be careful when converting to the byte array, otherwise it will be a noise with barely recognizable source sound.
short[] input16 = ... // the source 16-bit audio data;
byte[] output8 = new byte[input16.length];
for (int i = 0 ; i < input16.length ; i++) {
// To convert 16 bit signed sample to 8 bit unsigned
// We add 128 (for rounding), then shift it right 8 positions
// Then add 128 to be in range 0..255
int sample = ((input16[i] + 128) >> 8) + 128;
if (sample > 255) sample = 255; // strip out overload
output8[i] = (byte)(sample); // cast to signed byte type
}
To perform backward conversion all should be the same: each single sample to be converted to exactly one sample of the output signal
byte[] input8 = // source 8-bit unsigned audio data;
short[] output16 = new short[input8.length];
for (int i = 0 ; i < input8.length ; i++) {
// to convert signed byte back to unsigned value just use bitwise AND with 0xFF
// then we need subtract 128 offset
// Then, just scale up the value by 256 to fit 16-bit range
output16[i] = (short)(((input8[i] & 0xFF) - 128) * 256);
}
The issue of not being able to convert data from byte array to short array was resolved when used bitwise operators instead of using ByteArray. It could be due not setting the correct parameters in ByteArray or it is not suitable for such conversion.
Nevertheless implementing conversion using bitwise operators resolved the problem. Since the original question has been resolved by this approach, please consider this as the final answer.
I will raise a separate topic for playback issue.
Thank you for all your support.
I am coding a small software to send data with an RN2483 transciever, and I have realised that my data is converted to ASCII when I sent it through serial. It is to say, I have the following part in the sender, the data has to be HEX
String aux = String(message.charAt(i),HEX);
dataToBeTx = "radio tx " + aux+ "\r\n";
Serial1.print(dataToBeTx)
On the receiver I am reading Serial1 till I get the message, which I receive properly, however it is an ASCII representation of the HEX data, and I would like to have it HEX, I mean, I send HI that is converted to HEX (H I=>0x48 0x49) on the receiver if I translate that value to HEX again I got different things than my H or I , so I guess it is being encoded in ASCII, how can I ride off from that?
Thanks in advance,
regards
It is very unclear what you are trying to achieve. The first line in your code converts a single character into a string in hexadecimal. For example:
void setup ()
{
Serial.begin (115200);
Serial.println ();
String aux = String('A', HEX);
Serial.print ("aux = ");
Serial.println (aux);
} // end of setup
void loop ()
{
} // end of loop
Output:
aux = 41
So the 'A' in my code (internally represented as 0x41) has now become two ASCII characters: 4 and 1. That is, a string which is two bytes long.
So, in a sense, you can say it is already in hex.
if I translate that value to HEX again I got different things than my H or I
Well, yes, if you translate it "again" then you would get 0x34 and 0x31.
Do you want to send A in this case, 41 or something else?
I'm using this sensor with an arduino board.
On page 2, it describes the serial output from pin 5.
http://www.maxbotix.com/documents/HRXL-MaxSonar-WR_Datasheet.pdf
The output is an ASCII capital "R", followed by four ASCII character
digits representing the range in millimeters,followed by a carriage
return (ASCII 13). The serial data format is 9600 baud, 8 data bits, no parity,
with one stop bit (9600-8-N-1).
This is my arduino code (which isn't correct). It only outputs the '82' which is the capital R.
void setup()
{
Serial.begin(9600);
}
void loop()
{
int data = Serial.read();
Serial.println(data);
delay (1000);
}
How do I get a distance reading to a string?
Many thanks
Do you tried the readBytesUntil method ?
You should use it like that :
byte DataToRead [6];
Serial.readBytesUntil(char(13), DataToRead, 6);
Your data is contained into DataToRead (your 'R' in DataToRead[0] etc.)
As I read it, the question was:
How do you convert a byte (ascii) representation of a character into a readable alpha-numeric character like "a" versus 97?
The actual quesion: Arduino convert ascii characters to string.
Why do ppl post responses that don't answer the question?
Not exact answer but casting with (char) will get you on the way there.
char inByte = 0;
inByte = (char)Serial.read(); // ascii 97 received
Serial.println((char)inByte); // => prints an 'a' without the quotes
I am getting an int value from one of the analog pins on my Arduino. How do I concatenate this to a String and then convert the String to a char[]?
It was suggested that I try char msg[] = myString.getChars();, but I am receiving a message that getChars does not exist.
To convert and append an integer, use operator += (or member function concat):
String stringOne = "A long integer: ";
stringOne += 123456789;
To get the string as type char[], use toCharArray():
char charBuf[50];
stringOne.toCharArray(charBuf, 50)
In the example, there is only space for 49 characters (presuming it is terminated by null). You may want to make the size dynamic.
Overhead
The cost of bringing in String (it is not included if not used anywhere in the sketch), is approximately 1212 bytes of program memory (flash) and 48 bytes RAM.
This was measured using Arduino IDE version 1.8.10 (2019-09-13) for an Arduino Leonardo sketch.
Risk
There must be sufficient free RAM available. Otherwise, the result may be lockup/freeze of the application or other strange behaviour (UB).
Just as a reference, below is an example of how to convert between String and char[] with a dynamic length -
// Define
String str = "This is my string";
// Length (with one extra character for the null terminator)
int str_len = str.length() + 1;
// Prepare the character array (the buffer)
char char_array[str_len];
// Copy it over
str.toCharArray(char_array, str_len);
Yes, this is painfully obtuse for something as simple as a type conversion, but somehow it's the easiest way.
You can convert it to char* if you don't need a modifiable string by using:
(char*) yourString.c_str();
This would be very useful when you want to publish a String variable via MQTT in arduino.
None of that stuff worked. Here's a much simpler way .. the label str is the pointer to what IS an array...
String str = String(yourNumber, DEC); // Obviously .. get your int or byte into the string
str = str + '\r' + '\n'; // Add the required carriage return, optional line feed
byte str_len = str.length();
// Get the length of the whole lot .. C will kindly
// place a null at the end of the string which makes
// it by default an array[].
// The [0] element is the highest digit... so we
// have a separate place counter for the array...
byte arrayPointer = 0;
while (str_len)
{
// I was outputting the digits to the TX buffer
if ((UCSR0A & (1<<UDRE0))) // Is the TX buffer empty?
{
UDR0 = str[arrayPointer];
--str_len;
++arrayPointer;
}
}
With all the answers here, I'm surprised no one has brought up using itoa already built in.
It inserts the string representation of the integer into the given pointer.
int a = 4625;
char cStr[5]; // number of digits + 1 for null terminator
itoa(a, cStr, 10); // int value, pointer to string, base number
Or if you're unsure of the length of the string:
int b = 80085;
int len = String(b).length();
char cStr[len + 1]; // String.length() does not include the null terminator
itoa(b, cStr, 10); // or you could use String(b).toCharArray(cStr, len);