I am trying to manage some LED strips with my mobile device using bluetooth + Adafruit NeoPixel. I almost had the sketch finished but I have found the numbers for RGB are not appearing as I expected and I cannot find what I am doing wrong.
Imagine that from my mobile I have sent the following RGB code "0,19,255", when I check the console I see the following result:
As you can see the first two lines are ok, but the third one we can see 2550. The 0 should no be there and I cannot figure it out the problem.
So I decided isolate the code and try to keep the minimum to identify the root cause and this is the code:
#include <SoftwareSerial.h>
#include <Adafruit_NeoPixel.h>
SoftwareSerial BT (10, 11);
#define PIN 2
#define NUMPIXELS 144
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);
int red = "";
void setup() {
Serial.begin(9600);
Serial.println("Ready");
BT.begin(38400);
pixels.begin();
pixels.show();
pixels.setBrightness(20);
}
void loop() {
while (BT.available()>0){
red = BT.parseInt();
Serial.println(red);
}
}
You describe that for the shown output you sent via mobile "0,19,255".
Yet in the shown output that obviously is only the second part of a longer sequence of numbers sent, which starts with "0,21".
Assuming that what you send is always of the format you have described, i.e. three numbers, separated by two ",", the shown output is most likely the result of you sending first "0,21,255" and then another triplet "0,19,255".
These two messages together would end up in an input buffer "0,21,2550,19,255".
Now I have to do some speculation. Most parsers, when told to look for numbers within the buffer, will look for digits followed by non-digits. They would end up yielding "0,21,2550".
Without knowing details of the parsers working it is hard to say how to fix your problem.
I would however definitly experiment with sending triplets which end in a non-digit.
For example:
"0,21,255,"
or
"0,21,255 "
or
"0,21,255;"
If none of them work you might need to explicitly expect the non-digit, i.e. between triplets of numbers read a character and either ignore it or compare it to " ,", " " or ";" for additional self-checking features.
(Writing this I rely on user zdf not intending to make an answer, because while I did spot the "2550" as "255""0", zdf spotted the only two "," inside the question body in sample input, which I missed. I will of course adapt my answer to one created by zdf, to not use their contribution without their consent.)
Related
I'm using 3 command line tools via QProcesses to play music on my Linux (Mint) desktop via the Jack server. It's all working very well, but the input from one of the tools 'jack_showtime' arrives at about 12,000 lines per second.
I only need to see one line every 0.1 seconds, but the only way I've found to get a full recent line is like:
j_s->readAll(); // j_s is the jack_showtime QProcess
waitAbit(20); // a 20 mS delay
QString aShowtimeLine = j_s->readLine();
aShowtimeLine = j_s->readLine();
What would be a better way to deal with so much unwanted input? It seems that; without the readAll, a line will be much too old. Without the delay, I get a blank line and without the two readLines I get part of a line.
I'd also be interested in a Bash script that could absorb most of the input, or similar.
I suggest something like this, such that no matter how fast or how slow you get input from the child process, you always use the only most recent value, every 100mS:
// at startup or in your class constructor or wherever
connect(j_s, SIGNAL(readyRead()), this, SLOT(ReadDataFromJack()));
connect(&_myQTimer, SIGNAL(timeout()), this, SLOT(UseOneLine()));
_myQTimer.start(100);
void MyClass :: ReadDataFromJack()
{
while(j_s->canReadLine())
{
char buf[1024];
qint64 bytesRead = j_s->readLine(buf, sizeof(buf));
if ((bytes > 0)&&(CanParseText(buf))
{
this->_mostRecentResult = ParseText(buf);
}
}
}
void MyClass :: UseOneLine()
{
printf("100mS have elapsed, time to use _mostRecentResult=%i for something!\n", this->_mostRecentResult)
}
(Note that CanParseText(buf) and ParseText(buf) above are imaginary placeholders for whatever code you use to parse ASCII text coming from your child process into data to be used by your program)
Bulls eye! Thank you. You seem to know what I already had, so it was easy to add the bits I didn't have. Mainly the limited size buffer and, as I've never seen a line longer than 79 characters, I reduced it to 100. I may have been on the right track, while looking for a script solution, when I tried to use 'stdbuf', but dealing with it all in my program is much better.
Lines received are easy to parse. I only want the first number (which can be as low as zero) from something like this:
frame = 293532731 frame_time = 114978548 usecs = 2421437949 state: Rolling
I use the following, which seems reasonably minimal:
QString recentLine = QString::fromLocal8Bit(buf);
recentLine.remove(0,8);
recentLine.chop(recentLine.length() - recentLine.indexOf(" "));
int numSamples = recentLine.toInt();
I put a counter in the ReadDataFromJack() class and see between 2,000 and 3,000 visits per 100mS!
The number represents the position of the 'play head' in samples (at 48k per second) and wont exceed the integer range in Qt, but I see you use a qint64 (long long) in your example. Should I do the same for my number?
Sorry it's an answer (and a further question), but it's too long for a comment.
I am trying to send data from my BeagleBone black board to Arduino Uno. The baud rate I have selected is 300. I am using the serialib library which is located here: http://serialib.free.fr/html/classserialib.html#ac8988727fef8e5d86c9eced17876f609 you can scroll all the way to the bottom to view the two files (serialib.h and serialib.cpp), however I have posted the main snippets here too. I read some reviews saying that this library is not reliable however I would first want to check my code before really suspecting anything else.
This is the program I have written in C++ on my BeagleBone:
#include <iostream>
#include "serialib.h"
#ifdef __linux__
#define DEVICE_PORT "/dev/ttyO1"
#endif
using namespace std;
int main()
{
serialib LS; //the main class to access
int Ret;
Ret= LS.Open(DEVICE_PORT,300);
if (Ret!=1)
{
cout<<"cant open port\n";
return 0;
}
else{cout<<"port now open \n";}
string xval="650X450Y";
for(int i=0;i<500;i++)//send xval 500 times
{
for(int j=0;j<xval.length();j++)//send each character separately
{
Ret=LS.WriteChar(xval[j]);
LS.Close();
LS.Open(DEVICE_PORT,300);
}
if (Ret!=1){cout<<"cannot write\n";}
else{cout<<"done writing\n";}
}
LS.Close();
cout<<"Transmission complete\n";
}
My code on the Arduino Uno is as follows:
#include <SoftwareSerial.h>
SoftwareSerial uart(10,11);
void setup() {
// put your setup code here, to run once:
Serial.begin(9600); //baud rate for Serial communication
uart.begin(300);
}
char x;
String data="";
void loop()
{
if(uart.available()>0)//check if data is coming in
{
while(uart.available())
{
x=uart.read();//read the incoming byte
data+=x;//append the string with incoming bytes
}
if(x=='Y')//received all the bits
{
Serial.println(data); //display received information
}
}
}
C++ - I am first opening up my UART port on the BeagleBone and sending the string "650X450Y" character by character which is repeated 500 times to see if my communication system is robust or not. As you can see that within the 'for' loop I am closing and opening this port after sending every character because without this, it sends quite a lot of wrong data and if this 'for' loop is very big then the writing process even stops (not sure why it behaves like that) thus after closing and opening this port every time, I have managed to reduce the errors significantly but there are still a few errors:
I sent this string 500 times but one sample I received on the Uno was "660X450Y", wrong value.
About 2-3 times out of 500, I am receiving "650X450Y650X450Y650X450Y" i.e. repetitions, this is definitely not the string length then how come it can send this data?.
The rest of the strings I received on the Uno are perfect.
On the Uno as you can see that I am reading in character by character and appending it to my string named data and printing out this data as soon as the byte 'Y' is detected which denotes the end of the string. I previously used the WriteString() function in my C++ code however that gave a number of errors, The code I have provided is the closest I have come so far in the last few days to make this system 100% reliable and robust after lots of debugging, however I'm really not sure why the system is still not 100%.
I saw the source code of both the files in the library and observed the WriteChar(char Byte) function which is defined at line 210 in serialib.cpp (link already provided above) and I see that this is the function transmitting the characters:
if (write(fd,&Byte,1)!=1) // Write the char
return -1; // Error while writting
return 1; // Write operation successfull
I don't see anything wrong with this function then why can't I receive the data with 100% accuracy, Is there anything wrong in both my source codes or either one?, should I opt for a different serial library?, in case I opt for other libraries and I still don't get my results then I think I may have to transmit this info in a wireless manner for e.g using bluetooth modules. If anyone has any suggestions/improvements regarding this problem then do let me know :), till then I'll try other methods to achieve a 100% accuracy.
The easiest just to check if quickly can be done in the linux terminal and no library is used for that.
Set the baudrate to 300 for the UART1 (stty -F /dev/ttyO1 raw & stty -F /dev/ttyO1 300)
You can sent data to the UART1 simply by writing(or reading) to the device file for the UART1 which is in your case /dev/ttyO1
Writing: echo "650X450Y" > /dev/ttyO1
Reading: cat /dev/ttyO1
If you want to do this in C Code you can use the open/read/write/close syscall functions.
when I use <LiquidCrystal.h library and lcd-write() it only show the first 16 char in the fist row and start in the 41st char in the second row.
I started with lcd.begin(16,2).
Here an example of the code.
The result of this code will be:
row 1: 0123456789112345
row 2: 4123456789
#include <LiquidCrystal.h>
LiquidCrystal lcd(2,3,4,5,6,7);
void setup() {
// put your setup code here, to run once:
lcd.begin(16, 2);
Serial.begin(9600);
lcd.print("0123456789");
lcd.print("1123456789");
lcd.print("2123456789");
lcd.print("3123456789");
lcd.print("4123456789");
}
void loop() {
}
Its that the expected functionality?
There are a way so I can get the 17th char be displayed in second row.
Yes, that is the expected behaviour. The library allows you to control HD44780-based LCD modules. This LCD controller can drive displays up to 40 character by 2 lines in size. When you use a smaller module, the lines are still stored in the same locations in the DDRAM: the first line starts at location 0, the second line starts at location 40. See the datasheet for more information:
https://www.sparkfun.com/datasheets/LCD/HD44780.pdf
You can use the entire memory and scroll left and right since the 16-character wide display is a window into the DDRAM. You can use the scrollDisplayLeft and scrollDisplayRight to shift the display left and right. These functions change which DDRAM address is used for the first character on the far left of the display. Both lines scroll in unison.
I'm not completely sure why your Arduino has this behaviour but you can pass a complete line in your case 16 characters every time you print and look how it works, also parsing in variables ant passing it to the .print method.
Another way is to set manually the data in the row that you want using the setCursor() method, this method helps you to move and print in the position that you want, it receives two parameters the column and the row, I'll let you the URL with more information.
https://www.arduino.cc/en/Tutorial/LiquidCrystalSetCursor
I have a static method that searches (and returns) into String msg the value between a TAG
this is the code function:
static String genericCutterMessage(String TAG, String msg){
Serial.print("a-----");
Serial.println(msg);
Serial.print("b-----");
Serial.println(TAG);
if(msg.indexOf(TAG) >= 0){
Serial.print("msg ");
Serial.println(msg);
int startTx = msg.indexOf(TAG)+3;
int endTx = msg.indexOf(TAG,startTx)-2;
Serial.print("startTx ");
Serial.println(startTx);
Serial.print("endTx ");
Serial.println(endTx);
String newMsg = msg.substring(startTx,endTx);
Serial.print("d-----");
Serial.println(newMsg);
Serial.println("END");
Serial.println(newMsg.length());
return newMsg;
} else {
Serial.println("d-----TAG NOT FOUND");
return "";
}
}
and this is output
a-----[HS][TS]5132[/TS][TO]5000[/TO][/HS]
b-----HS
msg [HS][TS]5132[/TS][TO]5000[/TO][/HS]
startTx 4
endTx 30
d-----
END
0
fake -_-'....go on! <-- print out of genericCutterMessage
in that case I want return the string between HS tag, so my expected output is
[TS]5132[/TS][TO]5000[/TO]
but I don't know why I receive a void string.
to understand how substring works I just followed tutorial on official Arduino site
http://www.arduino.cc/en/Tutorial/StringSubstring
I'm not an expert in C++ and Arduino but this looks like a flushing or buffering problem, isn't it?
Any idea?
Your code is correct, this should not happen. Which forces you to consider the unexpected ways that this could possibly fail. There is really only one candidate mishap I can think of, your Arduino is running out of RAM. It has very little, the Uno only has 2 kilobytes for example. It doesn't take a lot of string munching to fill that up.
This is not reported in a smooth way. All I can do is point you to the relevant company page. Quoting:
If you run out of SRAM, your program may fail in unexpected ways; it will appear to upload successfully, but not run, or run strangely. To check if this is happening, you can try commenting out or shortening the strings or other data structures in your sketch (without changing the code). If it then runs successfully, you're probably running out of SRAM. There are a few things you can do to address this problem:
If your sketch talks to a program running on a (desktop/laptop) computer, you can try shifting data or calculations to the computer, reducing the load on the Arduino.
If you have lookup tables or other large arrays, use the smallest data type necessary to store the values you need; for example, an int takes up two bytes, while a byte uses only one (but can store a smaller range of values).
If you don't need to modify the strings or data while your sketch is running, you can store them in flash (program) memory instead of SRAM; to do this, use the PROGMEM keyword.
That's not very helpful in your specific case, you'll have to look at the rest of the program for candidates. Or upgrade your hardware, StackExchange has a dedicated site for Arduino enthusiasts, surely the best place to get advice.
Referring to two questions:
Incorrect output from C++ Primer 1.4.4
Confused by control flow execution in C++ Primer example
My question is answered in both of those posts, but I want to delve further.
First, I know this is only the beginning, but let's say I make a fully functional program that runs in a designed window. By that level, will I already know how to implement a EOF? I can't expect someone running my program to know that they need to hit Control-Z.
Is there a way to implement a specific code that functions so that it does not need me to type in an unrecognized value?
Also one guy in those questions somewhat answered the importance of EOF, but how come the program doesn't even post the final cnt - 1?
Let's say I do the numbers 10 10 10 20 20 20. Without EOF, this will only show the "10 repeats 3 times." How come the program doesn't at least type in the count "10 repeats 3 times and 20 repeats 2 times" minus the final one with white space?
lets say I make a fully functional program that runs in a designed window. By that level, will I already know how to implement a eof? I can't expect someone running my program to know that they need to hit ctrl + z.
You could either tell the user explicitly to do a specific action to end input or the design of the window itself could tell the user the information implicitly. For instance, a dialog box could ask the user to enter input and click an OK button when done.
Is there a way to implement a specific code that functions so that it does not need me to type in an unrecognized value?
It seems like you would rather use a newline character to terminate your input. An example of this usage could be std::getline. Instead of writing
while (std::cin >> val)
you could instead use
std::string line;
if (std::getline(std::cin,line))
and assume that your user's input only consists of one line of values. There are plenty of other ways to similarly achieve this task depending on how you want to constrain the user's input.
Let's say I do the numbers 10 10 10 20 20 20. WIthout eof this will only show the "10 repeats 3 times." How come the program doesn't at least type in the count "10 repeats 3 times and 20 repeats 2 times" minus the final one with white space?
Without the eof your program is still executing the while (std::cin >> val) loop since std::cin >> val has not yet received invalid input.
Since the line
std::cout << currVal << " occurs " << cnt << " times" << std::endl;
occurs after that while loop finishes execution, you don't (yet) see any information about the three 20's in the input.
When you are reading a sequence of inputs you'll need some indication when your down. That could be a sentinel value ("enter 999 to stop reading"; you'd need to detect that while reading), an invalid input ("enter X to stop reading"; when reading an int the value X is illegal and causes the stream to got into failure mode, i.e., have std::ios_base::failbit set), or the more conventional "there isn't anything more to read". For a file, the last conditions is straight forward. When reading data from the console you'll either need to teach people how to terminate the input or you'll need to use a different approach.
If you want to intercept any keypressed and react on them directly you may do so, too. You could, e.g., use ncurses and control your input via that. You could also set the concole to non-buffering (on POSIX systems using tcgetattr() and tcsetattr() to clear the ICANON flag) and deal directly with all key presses to decide whether you want to continue reading or not.
Although I'm certainly up to doing fancy I/O stuff I normally don't bother: users will understand the "end of input" character and just deal with it. That is, my input normally looks something like this:
while (in >> whatever_needs_to_be_read) { ... }
... or, if the input is genuinely line oriented
for (std::string line; std::getline(in, line); ) { ... }
The function doing this input will then be called with a suitable std::istream which may be std::cin although I have typically some way to also read from a file (in addition to the shell-privided input redirection).
BTW, despite some indications in the questions referenced, "EOF" is not a character being read. It is a character entered, though (normally). ... and it is quite conventional to "know" the end of input character (on POSIX systems a ctrl-D and on Windows a ctrl-Z). You can use other indicators, e.g., the "interrupt" (ctrl-C) but that takes more work and doesn't integrate nicely with stream. To use the interrupt chacter you'd need to setup a signal handler for SIGINT and deal with that. One slightly annoying part of doing so is that if you get it wrong you'll need to find a different way to kill the program (e.g. on POSIX using ctrl-Z to put the process to sleep and kill it via a harsher signal).