I am trying to work with the sim900, what I am trying to do, is: 1- read the serial port, 2- input everything into a string, 3- search a parameter in that string, 4- clean the string.
The code is really simple, but i cant understand what i am doing wrong.
If anyone make something similar, or knows how to do it I will be graceful.
Thank you very much
Jose Luis
String leido = " ";
void setup(){ // the Serial1 baud rate
Serial.begin(9600);
Serial1.begin(9600);
}
String leido = " ";
void setup(){
// the Serial1 baud rate
Serial.begin(9600);
Serial1.begin(9600);
}
void loop()
{
//if (Serial1.available()) { Serial.write(Serial1.read()); } // Sim900
if (Serial.available()) { Serial1.write(Serial.read()); } // pc
leido = LeerSerial();
Serial.println(leido);
if (find_text("READY",leido)==1){leido = " ";}
}
String LeerSerial(){
char character;
while(Serial1.available()) {
character = Serial1.read();
leido.concat(character);
delay (10); }
if (leido != "") { Serial1.println(leido);return leido; }
}
int find_text(String needle, String haystack) {
int foundpos = -1;
for (int i = 0; (i < haystack.length() - needle.length()); i++) {
if (haystack.substring(i,needle.length()+i) == needle) {
foundpos = 1;
}
}
return foundpos;
}
You shouldn't be using == to compare strings in C/C++, since that compares pointers. A better option is strcmp or even better strncmp, check this reference.
Back to your code, try something like this:
if (strncmp(haystack.substring(i,needle.length()+i), needle, needle.length()) == 0) {
foundpos = 1;
}
Can you get away by simply using String's indexOf() ?:
String leido = " ";
void setup() {
// the Serial1 baud rate
Serial.begin(9600);
Serial1.begin(9600);
}
void loop()
{
//if (Serial1.available()) { Serial.write(Serial1.read()); } // Sim900
if (Serial.available()) {
Serial1.write(Serial.read()); // pc
}
leido = LeerSerial();
Serial.println(leido);
if (leido.indexOf("READY") == 1) {
leido = " ";
}
}
String LeerSerial() {
char character;
while (Serial1.available()) {
character = Serial1.read();
leido.concat(character);
delay (10);
}
if (leido != "") {
Serial1.println(leido);
return leido;
}
}
Note that this assumes "READY" is always at index 1.
Maybe it's worth checking if the indexOf("READY") is greater than -1 (present in the string) ?
Related
im learning coding with arduino and c#. my program send by bluetooth commands to do for platform with stepper motors ( simple list of moves).
Step first - After recive informations, prepare them to use (format !,.(...)# (eg. !1,100.3,90.# mean move forward(1) for 100 ms, move left(3) 90 ms. ! -start of stream # - end of stream)
Step two - execute moves
Step three - if no more, proceed loop till next information come to Serial1 (which mean start step first.
And it even works, but after first recived string my Serial1.available() returns false ;/
i have no idea why? is he busy or what? i can't recive second string of commands
#define a1 4 //stepper motor connection
#define a2 3
#define b1 5
#define b2 6
int licznikRuch = 0; // counter for tabMove
int licznikCzas = 0;// counter for tabTime
int kolejka = 0;
bool CiagRuch = false;
bool CiagCzas = false; //
bool Zakonczono = false; //
int SubPoczatek, SubKoniec; // substring start / substring end
bool Wykonaj = false;
String tabMove[100];
String tabTime[100];
String inputString = "";
String StringCzas = "";
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial1.begin(9600); //
Serial2.begin(9600);
inputString.reserve(200);
for(int i = 0; i < 100; i++){
tabMove[i] = "";
tabTime[i] = "";
}
pinMode(19, OUTPUT);pinMode(17,OUTPUT);
pinMode(51,OUTPUT);
pinMode(a1, OUTPUT); pinMode(a2, OUTPUT);
pinMode(b1, OUTPUT); pinMode(b2, OUTPUT);
digitalWrite(a1,LOW); digitalWrite(a2,LOW);
digitalWrite(b1,LOW); digitalWrite(b2,LOW);
}
void loop() {
// put your main code here, to run repeatedly:
if(Zakonczono){ // operacje na wczytanym ciagu. wydobycie rozkazow i czasu
Serial.println(inputString);
for(int i = 0; i < inputString.length();i++){
if(inputString[i] == '!'){
for(int l =0;l<100;l++){
Wykonaj = false;
tabTime[l] = "";
tabMove[l] = "";
licznikCzas = 0;
licznikRuch = 0;
}
}
if(inputString[i] == '#'){
Wykonaj = true;
}
if(inputString[i] == '.'){
SubKoniec = i;
tabTime[licznikCzas++] = inputString.substring(SubPoczatek+1,SubKoniec);
CiagCzas = false;
StringCzas = "";
}
if(inputString[i] == ','){
tabMove[licznikRuch++] = inputString[i-1];
CiagCzas = true;
SubPoczatek = i;
}
}
for(int i = 0; i< licznikCzas;i++)
Serial.println(i+"Ruch"+tabMove[i]+"Czas:"+tabTime[i]);
Zakonczono = false;
inputString= "";
}
while(Wykonaj) // if you cut off whole this loop Serial1 is still available and recive commands
{
if(tabMove[kolejka] == "1") // move forward
{
digitalWrite(a1,LOW);
digitalWrite(a2,HIGH);
digitalWrite(b1,LOW);
digitalWrite(b2,HIGH);
delay(tabTime[kolejka].c_str());
Serial.print("1");
digitalWrite(a1,LOW);
digitalWrite(a2,LOW);
digitalWrite(b1,LOW);
digitalWrite(b2,LOW);
kolejka++;
// Serial.print(kolejka);
}
if(tabMove[kolejka] == "2"){ // left
digitalWrite(a1,LOW);
digitalWrite(a2,HIGH);
digitalWrite(b1,HIGH);
digitalWrite(b2,LOW);
delay(tabTime[kolejka].c_str());
Serial.print("2");
digitalWrite(a1,LOW);
digitalWrite(a2,LOW);
digitalWrite(b1,LOW);
digitalWrite(b2,LOW);
kolejka++;
}
if(tabMove[kolejka] == "3"){ // right
digitalWrite(a1,HIGH);
digitalWrite(a2,LOW);
digitalWrite(b1,LOW);
digitalWrite(b2,HIGH);
delay(tabTime[kolejka].c_str());
Serial.print("3");
digitalWrite(a1,LOW);
digitalWrite(a2,LOW);
digitalWrite(b1,LOW);
digitalWrite(b2,LOW);
kolejka++;
}
if(tabMove[kolejka] == "4"){ // back
digitalWrite(a1,HIGH);
digitalWrite(a2,LOW);
digitalWrite(b1,HIGH);
digitalWrite(b2,LOW);
delay(tabTime[kolejka].c_str());
Serial.print("3");
digitalWrite(a1,LOW);
digitalWrite(a2,LOW);
digitalWrite(b1,LOW);
digitalWrite(b2,LOW);
kolejka++;
}
if(tabMove[kolejka] == ""){
Wykonaj = false;
if(!Serial1.available())
Serial.print("Serial1 not avaliable ;("); // ???
break;
}
}
}
void serialEvent1(){
char Znak = "_";
// char PoprzedniZnak = Znak;
while(Serial1.available()){
// Serial.write(Znak);
Znak = (char)Serial1.read();
inputString+= Znak;
if(Znak == '\n')
Zakonczono = true;
kolejka = 0;
}
}
Alright, first of all, let's get out of the way the silly things:
Have your tried to connect/reconnect the usb from your pc to arduino?
Have you tried to restart your pc and unplug the usb?
Have you checked that you have NO wire attached to pin 0 (RX) pin once you upload the code? This is a very common mistake, if it's the case take out the wire from pin 0 before you upload, then upload and put in the wire again after the upload is FULLY complete (you will get the white writings when it is)
Make sure that your pc drives are up to date, and you can see the serial in both your periferials, AND the IDE and it's connected properly
Ok now that this is out the way, a few suggestions:
Write the error number in the post, Serial.available is false, does not mean anything, should Serial.available = true and then something happens and you trigger the condition of Serial.available false?
Your code is a mess (no offense), make sure you make it a little nicer if you want others to give it a shot!
Now to your problem:
I don't know wheter you mean that your code is bad or it's the serial as serial port that is going ape.
So here is 2 solutions
For the code:
What you wrote here will not work and that's why the serial is not available:
void serialEvent1(){
char Znak = "_";
// char PoprzedniZnak = Znak;
while(Serial1.available()){ //What kind of condition is this?
// Serial.write(Znak);
Znak = (char)Serial1.read(); //This does not work! Why using char and convert when
//You can use a string!
inputString+= Znak;
if(Znak == '\n')
Zakonczono = true;
kolejka = 0;
}
}
It should be this:
void serialEvent1(){
String Znak = "_";
while(Serial1.available() == 0){
// Serial.write(Znak);
Znak = Serial1.readString();
inputString+= Znak;
if(Znak == '\n') //This is quite weird if a char or a String ==
//enter(button)?
Zakonczono = true;
kolejka = 0;
}
}
0 if you want it to start on an input into the serial, plus I would SERIOUSLY recommended that you do not use a while loop if this is a choice program, unless you encompass all the choices in the while loop and then you have another while loop that takes care of other choices
But said that let's go over the second solution:
Serial as in hardware:
You have to write me the error number you are getting otherwise I cannot help you, check my steps above and make sure that you are not making one of those mistakes, if you are not please write your error number in the post.
Hope it helped!
And that I wasn't too harsh ;)
I very new to Arduino Uno and need some advice....so here we go.
I want to use my Arduino to:
1. read my serial data --received as plain text
2. look for a specific word within a line of data received
3. only transmit/print the complete string if it contains the specific "word"
I found this sketch and it works only if I'm looking for char
// Example 3 - Receive with start- and end-markers
const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;
void setup() {
Serial.begin(9600);
Serial.println("<Arduino is ready>");
}
void loop() {
recvWithStartEndMarkers();
showNewData();
}
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
void showNewData() {
if (newData == true) {
Serial.print("This just in ... ");
Serial.println(receivedChars);
newData = false;
}
}
I think it is better to use String class methods.
you can get the Data using Serial.readString()
then use the String methods for looking for a specific word.
Here are some useful links
https://www.arduino.cc/en/Serial/ReadString
https://www.arduino.cc/en/Reference/StringObject
I'm having this little problem with some easy code, basically what I'm doing is sending information via the serial port via a program I wrote in Java. The information is getting their for basic statements (IE, can turn on lights and stuff) but I'm having errors getting it to decode strings with number values send to it.
So for example, I'm sending strings that look like this
BS//:+000/+000/+000
and the decoding method I'm using looks like this.
After adding the string via this:
if (inputString.startsWith("BS//:")) //**fixed
{
inputInfoToBaseStepper(inputString);
baseStepperRunAction(baseStepperRotCount, baseStepperRotStepSize, baseStepperTime);
}
Sends it too...
void inputInfoToBaseStepper(String baseStepper)
{
baseStepperRotCount = baseStepper.substring(6,9).toInt();
baseStepperRotStepSize = baseStepper.substring(10,13).toInt();
baseStepperTime = baseStepper.substring(15,18).toInt();
}
Which should decode and run
void baseStepperRunAction (int rotations, int StepSize, int delayTime)
{
for (int rotations; rotations >=0; rotations--)
{
baseStepper.step(StepSize);
delay(delayTime);
}
}
Problem seems to be that it doesn't decode... ideas I'm sort of lost at this stage. :/
(total past of the code, I know the information is getting there, just not compiling like it should.)
#include <Stepper.h>
//#include <HardwareSerial.h>
// int intensity = 0; // led intensity this is needed just as example for this sketch
String inputString = ""; // a string to hold incoming data (this is general code you can reuse)
boolean stringComplete = false; // whether the string is complete (this is general code you can reuse)
int stepsPerRevolution = 64; //at 5.625 degrees a step
// initialize the stepper library on pins 8 through 11:
Stepper baseStepper(stepsPerRevolution, 2,3,4,5); // protocols start with //BS:
Stepper shoulderStepper(stepsPerRevolution, 6,7,8,9); // protocols start with //SS:
Stepper armStepper(stepsPerRevolution, 10,11,12,13); // protocols start with //AS:
//--------baseStepper--------//
int baseStepperRotCount = 0; //how many rotations in the for loop is needed
int baseStepperRotStepSize = 0; // how large should the steps be...
int baseStepperTime = 0; //delay time needed between each step (delay); so the stepper can do it's work.
//--------shoulderStepper--------//
int shoulderStepperRotCount =0;
void setup() {
// initialize serial: (this is general code you can reuse)
Serial.begin(115200);
}
void loop() {
// when a newline arrives:
if (stringComplete) {
//these are test if statements, they serve no purpose after the intial boot, but must be included to test the connectivity;
if (inputString.startsWith("alpha"))
{
boolean msgRecognized = true;
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
inputString = "";
stringComplete = false;
}
else if (inputString.startsWith("beta"))
{
boolean msgRecognized = true;
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
inputString = "";
stringComplete = false;
}
//---------------------///
//these statements set the engines and prepare for running of the program.
if (inputString.startsWith("//BS:")) // "BS//:+000/+000/+000"
{
inputInfoToBaseStepper(inputString);
baseStepperRunAction(baseStepperRotCount, baseStepperRotStepSize, baseStepperTime);
}
else if (inputString.startsWith("//SS:"))
{
//inputInfoToShoulderStepper();
//outputConfirmed();
}
else if (inputString.startsWith("//AS:"))
{
//inputInfoToArmStepper();
// outputConfirmed();
}
if(inputString.startsWith("alp://")) { // OK is a message I know (this is general code you can reuse)
boolean msgRecognized = true;
if(inputString.substring(6,10) == "kprs") { // KeyPressed }
msgRecognized = false; // this sketch doesn't know other messages in this case command is ko (not ok)
// Prepare reply message if caller supply a message id (this is general code you can reuse)
int idPosition = inputString.indexOf("?id=");
if(idPosition != -1) {
String id = inputString.substring(idPosition + 4);
// print the reply
Serial.print("alp://rply/");
if(msgRecognized) { // this sketch doesn't know other messages in this case command is ko (not ok)
Serial.print("ok?id=");
} else {
Serial.print("ko?id=");
}
Serial.print(id);
Serial.write(255); // End of Message
Serial.flush();
}
}
// clear the string:
inputString = "";
stringComplete = false;
}
}
}
/*
Send listen messages
int index = 0;
for (index = 0; index < digitalPinListeningNum; index++) {
if(digitalPinListening[index] == true) {
int value = digitalRead(index);
if(value != digitalPinListenedValue[index]) {
digitalPinListenedValue[index] = value;
Serial.print("alp://dred/");
Serial.print(index);
Serial.print("/");
Serial.print(value);
Serial.write(255);
Serial.flush();
}
}
}
for (index = 0; index < analogPinListeningNum; index++) {
if(analogPinListening[index] == true) {
int value = analogRead(index);
if(value != analogPinListenedValue[index]) {
analogPinListenedValue[index] = value;
Serial.print("alp://ared/");
Serial.print(index);
Serial.print("/");
Serial.print(value);
Serial.write(255); // End of Message
Serial.flush();
}
}
}
} */
//this method decodes and stores inputs
void inputInfoToBaseStepper(String baseStepper)
{
baseStepperRotCount = baseStepper.substring(6,9).toInt(); // B S / / : + 0 0 0 / + 0 0 0 / + 0 0 0
baseStepperRotStepSize = baseStepper.substring(10,13).toInt();// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
baseStepperTime = baseStepper.substring(15,18).toInt();
}
//this method runs the base stepper off the decoded actions.
void baseStepperRunAction (int rotations, int StepSize, int delayTime)
{
for (int rotations; rotations >=0; rotations--)
{
baseStepper.step(StepSize);
delay(delayTime);
}
}
/*
SerialEvent occurs whenever a new data comes in the
hardware serial RX. This routine is run between each
time loop() runs, so using delay inside loop can delay
response. Multiple bytes of data may be available.
This is general code you can reuse.
*/
void serialEvent() {
while (Serial.available() && !stringComplete) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}
Whenever I run this code, it works pretty smoothly, until the while loop runs through once. It will go back and ask for the name again, and then skip String b = sc.nextLine();, and print the next line, instead.
static Scanner sc = new Scanner(System.in);
static public void main(String [] argv) {
Name();
}
static public void Name() {
boolean again = false;
do
{
System.out.println("What is your name?");
String b = sc.nextLine();
System.out.println("Ah, so your name is " + b +"?\n" +
"(y//n)");
int a = getYN();
System.out.println(a + "! Good.");
again = askQuestion();
} while(again);
}
static public boolean askQuestion() {
System.out.println("Do you want to try again?");
int answer = sc.nextInt();
if (answer == 1) {
return true;
}
else {
return false;
}
}
static int getYN() {
switch (sc.nextLine().substring(0, 1).toLowerCase()) {
case "y":
return 1;
case "n":
return 0;
default:
return 2;
}
}
}
Also, I'm trying to create this program in a way that I can ask three questions (like someone's Name, Gender, and Age, maybe more like race and whatnot), and then bring all of those answers back. Like, at the very end, say, "So, your name is + name +, you are + gender +, and you are + age + years old? Yes/No." Something along those lines. I know there's a way to do it, but I don't know how to save those responses anywhere, and I can't grab them since they only occur in the instance of the method.
Don't try to scan text with nextLine() AFTER using nextInt() with the same scanner! It may cause problems. Open a scanner method for ints only...it's recommended.
You could always parse the String answer of the scanner.
Also, using scanner this way is not a good practice, you could organize questions in array an choose a loop reading for a unique scanner instantiation like this:
public class a {
private static String InputName;
private static String Sex;
private static String Age;
private static String input;
static Scanner sc ;
static public void main(String [] argv) {
Name();
}
static public void Name() {
sc = new Scanner(System.in);
String[] questions = {"Name?","Age","Sex?"};//
int a = 0;
System.out.println(questions[a]);
while (sc.hasNext()) {
input = sc.next();
setVariable(a, input);
if(input.equalsIgnoreCase("no")){
sc.close();
break;
}
else if(a>questions.length -1)
{
a = 0;
}
else{
a++;
}
if(a>questions.length -1){
System.out.println("Fine " + InputName
+ " so you are " + Age + " years old and " + Sex + "." );
Age = null;
Sex = null;
InputName = null;
System.out.println("Loop again?");
}
if(!input.equalsIgnoreCase("no") && a<questions.length){
System.out.println(questions[a]);
}
}
}
static void setVariable(int a, String Field) {
switch (a) {
case 0:
InputName = Field;
return;
case 1:
Age = Field;
return;
case 2:
Sex = Field;
return;
}
}
}
Pay attention on the global variables, wich stores your info until you set them null or empty...you could use them to the final affirmation.
Hope this helps!
Hope this helps!
I was recently asked this question in an interview:
"How could you parse a string of the form '12345' into its integer representation 12345 without using any library functions, and regardless of language?"
I thought of two answers, but the interviewer said there was a third. Here are my two solutions:
Solution 1: Keep a dictionary which maps '1' => 1, '2' => 2, etc. Then parse the string one character at a time, look up the character in your dictionary, and multiply by place value. Sum the results.
Solution 2: Parse the string one character at a time and subtract '0' from each character. This will give you '1' - '0' = 0x1, '2' - '0' = 0x2, etc. Again, multiply by place value and sum the results.
Can anyone think of what a third solution might be?
Thanks.
I expect this is what the interviewer was after:
number = "12345"
value = 0
for digit in number: //Read most significant digit first
value = value * 10 + valueOf(digit)
This method uses far less operations than the method you outlined.
Parse the string in oposite order, use one of the two methods for parsing the single digits, multiply the accumulator by 10 then add the digit to the accumulator.
This way you don't have to calculate the place value. By multiplying the accumulator by ten every time you get the same result.
Artelius's answer is extremely concise and language independent, but for those looking for a more detailed answer with explanation as well as a C and Java implementation can check out this page:
http://www.programminginterview.com/content/strings
Scroll down (or search) to "Practice Question: Convert an ASCII encoded string into an integer."
// java version
public static int convert(String s){
if(s == null || s.length() == 0){
throw new InvalidParameterException();
}
int ret = 0;
boolean isNegtive = false;
for(int i=0;i<s.length();i++){
char c = s.charAt(i);
if( i == 0 && (c == '-')){
isNegtive = true;
continue;
}
if(c - '0' < 0 || c - '0' > 10){
throw new InvalidParameterException();
}
int tmp = c - '0';
ret *= 10;
ret += tmp;
}
return isNegtive ? (ret - ret * 2) : ret;
}
//unit test
#Test
public void testConvert() {
int v = StringToInt.convert("123");
assertEquals(v, 123);
v = StringToInt.convert("-123");
assertEquals(v, -123);
v = StringToInt.convert("0");
assertEquals(v, 0);
}
#Test(expected=InvalidParameterException.class)
public void testInvalidParameterException() {
StringToInt.convert("e123");
}
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void testInvalidParameterException2() {
exception.expect(InvalidParameterException.class);
StringToInt.convert("-123r");
}
Keep a dictionary which maps all strings to their integer counterparts, up to some limit? Doesn't maybe make much sense, except that this probably is faster if the upper limit is small, e.g. two or three digits.
You could always try a binary search through a massive look up table of string representations!
No-one said anything about efficiency... :-)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int nod(long);
char * myitoa(long int n, char *s);
void main()
{
long int n;
char *s;
printf("Enter n");
scanf("%ld",&n);
s=myitoa(n,s);
puts(s);
}
int nod(long int n)
{
int m=0;
while(n>0)
{
n=n/10;
m++;
}
return m;
}
char * myitoa(long int n, char *s)
{
int d,i=0;
char cd;
s=(char*)malloc(nod(n));
while(n>0)
{
d=n%10;
cd=48+d;
s[i++]=cd;
n=n/10;
}
s[i]='\0';
strrev(s);
return s;
}
This is Complete program with all conditions positive, negative without using library
import java.util.Scanner;
public class StringToInt {
public static void main(String args[]) {
String inputString;
Scanner s = new Scanner(System.in);
inputString = s.nextLine();
if (!inputString.matches("([+-]?([0-9]*[.])?[0-9]+)")) {
System.out.println("error!!!");
} else {
Double result2 = getNumber(inputString);
System.out.println("result = " + result2);
}
}
public static Double getNumber(String number) {
Double result = 0.0;
Double beforeDecimal = 0.0;
Double afterDecimal = 0.0;
Double afterDecimalCount = 0.0;
int signBit = 1;
boolean flag = false;
int count = number.length();
if (number.charAt(0) == '-') {
signBit = -1;
flag = true;
} else if (number.charAt(0) == '+') {
flag = true;
}
for (int i = 0; i < count; i++) {
if (flag && i == 0) {
continue;
}
if (afterDecimalCount == 0.0) {
if (number.charAt(i) - '.' == 0) {
afterDecimalCount++;
} else {
beforeDecimal = beforeDecimal * 10 + (number.charAt(i) - '0');
}
} else {
afterDecimal = afterDecimal * 10 + number.charAt(i) - ('0');
afterDecimalCount = afterDecimalCount * 10;
}
}
if (afterDecimalCount != 0.0) {
afterDecimal = afterDecimal / afterDecimalCount;
result = beforeDecimal + afterDecimal;
} else {
result = beforeDecimal;
}
return result * signBit;
}
}