I have written the following code. I want the string returned from the method
displayInfo( )
to be updated and printed just once, but the method sends strings repeatedly. If I copy the same code in void setup( ) function it is not printing any value.
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
static const int RXPin = 12, TXPin = 13;
static const uint32_t GPSBaud = 9600;
// The TinyGPS++ object
TinyGPSPlus gps;
// The serial connection to the GPS
SoftwareSerial ss(RXPin, TXPin);
String msg="";
String message="";
void setup()
{
Serial.begin(9600);
ss.begin(GPSBaud);
}
void loop()
{
while (ss.available() > 0)
if (gps.encode(ss.read()))
message = displayInfo();
Serial.print(message);
}
String displayInfo()
{
if (gps.location.isValid())
{
String lati=String(gps.location.lat(), 3);
String logi=String(gps.location.lng(),3);
msg=lati+","+logi+"\n";
return(msg);
}
}
I have updated the code to recover some of the errors like function returning value with a global variable but it still does not provide me a single String value even after I had put the void loop( ) code in void setup( )
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
static const int RXPin = 12, TXPin = 13;
static const uint32_t GPSBaud = 9600;
// The TinyGPS++ object
TinyGPSPlus gps;
// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);
String msg="";
void setup()
{
Serial.begin(9600);
ss.begin(GPSBaud);
while (ss.available()>0)
if (gps.encode(ss.read()))
displayInfo();
Serial.print(msg);
}
void loop()
{
// This sketch displays information every time a new sentence is correctly encoded.
}
void displayInfo()
{
//Serial.print(F("Location: "));
if (gps.location.isValid())
{
String lati=String(gps.location.lat(), 3);
String longi=String(gps.location.lng(), 3);
msg="location: "+lati+","+longi+"\n";
}
else
{
msg=msg+"invalid";
}
}
EDIT:
The ss (SoftwareSerial) has a buffer wich contains the data that is ready to be send. ss.begin() will return 0 in your setup since the buffer is still empty, therefore the while loop will not be iterated even once.
The loop() function of the arduino works like a while so by placing the content of that while loop, and replacing the while with an if, you will be able to keep testing until you have a message in the buffer.
By adding a boolean to check if you have already sent a message, you can make sure only 1 message will be sent.
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
static const int RXPin = 12, TXPin = 13;
static const uint32_t GPSBaud = 9600;
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
boolean sent = false;
void setup()
{
Serial.begin(9600);
ss.begin(GPSBaud);
}
void loop()
{
if (ss.available()>0 && sent == false){
if (gps.encode(ss.read())){
String msg = displayInfo();
if (msg != NULL){
Serial.print(msg);
sent = true;
}
}
}
}
String displayInfo()
{
if (gps.location.isValid())
{
String msg="";
String lati=String(gps.location.lat(), 3);
String logi=String(gps.location.lng(),3);
msg=lati+","+logi+"\n";
return(msg);
}
else{
return NULL;
}
}
By returning a NULL in the displayinfo()'s else statement, and testing for it within the loop(), you can ensure that you will only print a message when everything was working.
Related
Hello I am programming a bluetooth connection from Android Studio to Arduino. The connection works and it sends the String. I only get something like this tho on my Arduino (x?xx?xx??xxx?xxx?x) the questionmarks are the other way the string I send is on
This is my code:
#include <SoftwareSerial.h>
#define rxPort 11
#define txPort 10
char btData;
String string;
SoftwareSerial btSerial(rxPort, txPort);
void setup(){
Serial.begin(9600);
btSerial.begin(38400);
Serial.println("bluetooth available");
pinMode(LED_BUILTIN, OUTPUT);
}
void loop(){
if(btSerial.available()>0){
string = "";
}
while(btSerial.available()>0){
btData = (byte)btSerial.read();
if(btData==":"){
break;
}else{
string += btData;
}
delay(1);
Serial.println(string);
}
if(string == "on"){
digitalWrite(LED_BUILTIN,HIGH);
}
}
why do you cast the read to byte??
char it is :)
it should work with 9600 BAUD rate as well
example from my project (I didn't build String though - used single char as command)
SoftwareSerial blue(3, 5); // BlueTooth RX, TX;
void BluetoothSetup()
{
blue.begin(9600);
blue.print("AT+NAMEKuku"); // give it a name
delay(2000);
Serial.println("got BT");
}
void setup() {
....
BluetoothSetup();
....
}
void loop() {
if (blue.available()) {
char r = blue.read();
ProcessRemoteCommand(r);
}
}
I have Arduino and a Duinotech NRF24L01, I am trying to send the string "Hello world" with maniacs bug RF24 library however, I think it cannot detect the incoming RF signal.
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
RF24 radio(7, 8); // CE, CSN
const uint64_t pipe = 0xF0F0F0F0E1L;
void setup() {
Serial.begin(9600);
radio.begin();
radio.openReadingPipe(0, pipe);
radio.startListening();
}
void loop() {
if (radio.available()) {
char text[32] = "";
radio.read(&text, sizeof(text));
Serial.println(text);
}
else {
Serial.println("Data was not found");
}
In the read code, it would always execute data was not found. This makes me think that maybe it does not find the RF signal at all.
Here is the code that writes the data.
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
RF24 radio(7, 8); // CE, CSN
int text = 1;
const uint64_t pipe = 0xF0F0F0F0E1LL;
void setup() {
Serial.begin(9600);
radio.begin();
radio.openWritingPipe(pipe);
radio.stopListening();
}
void loop() {
radio.write(&text, sizeof(text));
Serial.println("Sending Data");
delay(1000);
}
Try this
For the transmitter Instead of const uint64_t pipe = 0xF0F0F0F0E1LL; use const byte address[6] = "00001"; as the address and then have you void setup like the code below
void setup() {
radio.begin();
radio.openWritingPipe(address);
radio.setPALevel(RF24_PA_MIN);
radio.stopListening();
}
Then ensure that you have a value set for the test variable to be transmitted as below
void loop() {
const char text[] = "Hello World";
radio.write(&text, sizeof(text));
Serial.println("Sending Data");
delay(1000);
}
At the receiver end have this code running
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(7, 8); // CE, CSN
const byte address[6] = "00001";
void setup() {
Serial.begin(9600);
radio.begin();
radio.openReadingPipe(0, address);
radio.setPALevel(RF24_PA_MIN);
radio.startListening();
}
void loop() {
if (radio.available()) {
char text[32] = "";
radio.read(&text, sizeof(text));
Serial.println(text); //This will print out the received value
}
}
PS: Ensure that all the connections are done to the right pins
AND you can test if the NRF24L01 chip is connected correctly by adding the code below
bool result = radio.isChipConnected ();
Serial.println (result);
it should print out a 1 to the serial monitor if the NRF24L01 chip is connected correctly
My goal is to essentially spoof RSSI (Received Signal Strength Indicator) using a system of counting received packets. The idea is to have something where:
A specific number of packets is sent in a specific time from the transmitter.
Then are received at another unit and the number of packets received is counted.
The number in the counter of the receiver indicates the number of packets received at that time specific in the transmitter.
The fewer packages (counter value) that are received, the farther the sender will be.
I'm having a little trouble implementing the logic in my code however so I'd really appreciate the help. I am using Arduino Pro Mini 5V with NRF24L01+ radios and the RF24 Network library. My code is as follows:
Transmitter:
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#include <Wire.h>
RF24 radio(8,9);
RF24Network network(radio);
const uint16_t home_node = 00;
const uint16_t distant_node = 01;
struct payload_t { // Structure of our payload
byte ID;
};
void setup(void) {
Serial.begin(115200);
SPI.begin();
radio.begin();
network.begin(/*channel*/ 92, /*node address*/ distant_node);
}
void loop(void) {
byte ID = 1;
for (int i = 0; i < 50; i++)
{
payload_t payload = {ID};
RF24NetworkHeader header(/*to node*/ home_node);
bool ok = network.write(header,&payload,sizeof(payload));
if (ok)
Serial.println("ok.");
else
Serial.println("failed.");
delay (300);
}
delay(15000);
}
Receiver:
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#include <Wire.h>
RF24 radio(8,9);
RF24Network network(radio);
const uint16_t home_node = 00;
const uint16_t distant_node = 01;
struct payload_t {
byte ID;
};
//const unsigned long interval = 3000;
//unsigned long last_sent;
int count = 0;
void setup(void)
{
Serial.begin(115200);
SPI.begin();
radio.begin();
network.begin(/*channel*/ 92, /*node address*/ home_node);
}
void loop(void)
{
RF24NetworkHeader header;
payload_t payload;
network.update();
while ( network.available() ) { // Is there anything ready for us?
bool ok = network.read(header, &payload, sizeof(payload));
if (ok) // Non-blocking
{
count++;
Serial.println ("count=");
Serial.println (count);
}
else
Serial.println ("Failed");
}
}
I have multiple variable length strings which do not exceed 32 bytes each which need to be sent via I2C between 2 Arduino Nanos. I use # to terminate each string. I can successfully send and receive the first string, but for the life of me I can't figure out how to send the succeeding strings. The samples I am testing with look like this:
String answer = "12345,123.4,50.6,12345#";
String answerV = "4.10,4.15,4.13,4.05,4.18,0#";
Master Code
#include <Wire.h>
int esc = 0;
int throttle = 80;
void setup() {
Wire.begin();
Serial.begin(115200);
Serial.println("I2C Master ready!");
esc = throttle * 100 / 180;
}
void loop() {
delay(500);
Serial.println("Receive data");
Wire.requestFrom(9,32);
String response = "";
Serial.println(Wire.available());
while (Wire.available())
{
char b = Wire.read();
response += b;
}
String dataString = response;
int hashIndex = dataString.indexOf('#');
String SportData = dataString.substring(0, hashIndex);
Serial.println(SportData);
String SDdata = String (esc) + "," + String(SportData);
Serial.println(SDdata);
}
Slave Code
#include <Wire.h>
byte ANSWERSIZE= 22;
String answer = "12345,123.4,50.6,12345#";
String answerV = "4.10,4.15,4.13,4.05,4.18,0#";
void setup() {
Wire.begin(9);
Wire.onRequest(requestEvent); // data request from Master
Serial.begin(115200);
Serial.println("I2C Slave ready!");
ANSWERSIZE = answer.length();
}
void requestEvent() {
byte response[ANSWERSIZE];
for (byte i=0;i<ANSWERSIZE;i++)
{
response[i] = (byte)answer.charAt(i);
}
Wire.write(response,sizeof(response));
}
void loop() {
delay(50);
}
Can someone please show me how this can be done?
A simple idea is to keep track of the number of times requestEvent() is called, and use that to decide what to send back to the master.
Here is the code (n.b. I took the liberty to optimise it a bit):
Master:
#include <Wire.h>
/**
* globals
*/
int esc = 0;
int throttle = 80;
char i2c_buffer[33];
/**
* setup & loop
*/
void setup()
{
Serial.begin(115200);
Wire.begin();
esc = throttle * 100 / 180;
i2c_buffer[32] = '\0';
Serial.println("I2C Master ready!");
}
void loop()
{
delay(500);
Wire.requestFrom(9, 32);
for (byte i = 0; i < 32 && Wire.available(); ++i)
{
i2c_buffer[i] = Wire.read();
if (i2c_buffer[i] == '#') {
i2c_buffer[i] = '\0';
break;
}
}
Serial.print(esc);
Serial.print(',');
Serial.println(i2c_buffer);
}
Slave:
#include <Wire.h>
/**
* globals
*/
const byte DATA_SIZE = 2;
String data[DATA_SIZE] = {
"12345,123.4,50.6,12345#",
"4.10,4.15,4.13,4.05,4.18,0#"
};
/**
* setup & loop
*/
void setup()
{
Serial.begin(115200);
Wire.begin(9);
Wire.onRequest(requestEvent); // data request from Master
Serial.println("I2C Slave ready!");
}
void loop()
{
delay(50);
}
/**
* help functions
*/
void requestEvent()
{
static byte req_number = 0;
Wire.write(reinterpret_cast<const unsigned char*>(data[req_number].c_str()),
data[req_number].length());
req_number = (req_number + 1) % DATA_SIZE;
}
Note: I don't have two Arduino devices, so I could not test this code. If you spot some bugs, report back and I'll fix them.
I'm trying to convert Sparkfun's example code for the SM130 RFID Reader into a class/library that's encapsulated nicely and can be used in multiple arduino sketches.
Sparkfun Example Code: https://github.com/sparkfun/RFID_Evaluation_Shield/blob/master/Firmware/RFID_Eval_13_56MHz.ino
Most of it went pretty smoothly, until I tried to make the Software Serial communications a member variable -- I keep getting errors like:
/Users/scottnla/Dropbox/arduino/libraries/SM130/SM130.cpp: In constructor 'SM130::SM130()':
/Users/scottnla/Dropbox/arduino/libraries/SM130/SM130.cpp:8: error: no matching function for call to 'SoftwareSerial::SoftwareSerial()'
/Applications/Arduino.app/Contents/Resources/Java/libraries/SoftwareSerial/SoftwareSerial.h:83: note: candidates are: SoftwareSerial::SoftwareSerial(uint8_t, uint8_t, bool)
/Applications/Arduino.app/Contents/Resources/Java/libraries/SoftwareSerial/SoftwareSerial.h:48: note: SoftwareSerial::SoftwareSerial(const SoftwareSerial&)
I found a stackoverflow post that seems to address this issue (Creating a Library for an Arduino), but their solution doesn't seem to work for me. The IDE's error messages seem to indicate that I can only use a 'base initializer' in a constructor; but this isn't what I want. What's the best way to deal with the problem that I'm having in my code?
Thanks!
Code below:
SM130.h
#ifndef SM130_h
#define SM130_h
#include<Arduino.h>
#include <WConstants.h>
class SM130 {
public:
SM130();
void connect(int RX, int TX);
void check_for_notag();
void halt_tag();
void parse_tag();
void print_serial();
void seek_tag();
void set_flag();
private:
int rfid_flag;
int data[11];
SoftwareSerial rfid;
};
#endif
SM130.cpp
#include <WProgram.h>
#include <SoftwareSerial.h>
#include "SM130.h"
SM130::SM130() {
rfid_flag = 0;
}
void SM130::connect(int RX, int TX) : rfid(RX, TX) {
if(!Serial.available()) {
Serial.begin(9600);
}
Serial.println("Connecting to SM130 RFID Reader...");
//rfid = SoftwareSerial(RX, TX);
rfid.begin(19200);
if(rfid.available()) {
rfid.println("Connected to SM130 RFID Reader!");
}
delay(10);
}
void SM130::check_for_notag() {
seek_tag();
delay(10);
parse_tag();
set_flag();
if(rfid_flag == 1) {
seek_tag();
delay(10);
parse_tag();
}
}
void SM130::halt_tag() {
rfid.write(0xFF);
rfid.write((byte)0x00); //manual typecasting needed for 0x00 to differentiate it from null pointer -- silly c compilers!
rfid.write(0x01);
rfid.write(0x93);
rfid.write(0x94);
}
void SM130::parse_tag() {
while(rfid.available()) {
if(rfid.read() == 0xFF) {
for(int i = 1; i < 11; i++) {
data[i] = rfid.read();
}
}
}
}
void SM130::print_serial() {
if(rfid_flag == 1) {
Serial.print(data[5],HEX);
Serial.print(data[6],HEX);
Serial.print(data[7],HEX);
Serial.print(data[8],HEX);
Serial.println();
}
}
void SM130::seek_tag() {
//insert hex tags here
rfid.write(0xFF);
rfid.write((byte)0x00); //manual typecasting needed for 0x00 to differentiate it from null pointer -- silly c compilers!
rfid.write(0x01);
rfid.write(0x82);
rfid.write(0x83);
}
void SM130::set_flag() {
if(data[2] == 6) {
rfid_flag++;
}
if(data[2] == 2) {
rfid_flag = 0;
}
}
My arduino sketch:
#include <SM130.h>
void read_serial();
SM130 rfidReader;
void setup() {
//Connect to computer
Serial.begin(9600);
//connect to SM130
rfidReader.connect(7,8);
}
void loop() {
read_serial();
}
void read_serial() {
rfidReader.seek_tag();
delay(10);
rfidReader.parse_tag();
rfidReader.set_flag();
rfidReader.print_serial();
delay(100);
}
/Users/scottnla/Dropbox/arduino/libraries/SM130/SM130.cpp: In
constructor 'SM130::SM130()':
/Users/scottnla/Dropbox/arduino/libraries/SM130/SM130.cpp:8: error: no
matching function for call to 'SoftwareSerial::SoftwareSerial()'
This part tells you everything. SoftwareSerial has no constructor without argument list, so you try to call a non-existing function.
If you don't specify a class member in constructor's initialization list, compiler by default calls () constructor for it. It is equivalent of:
SoftwareSerial ss;
if we weren't talking about classes.
http://www.cprogramming.com/tutorial/initialization-lists-c++.html
Unfortunately SoftwareSerial has no Set methods.
http://arduino.cc/de/Reference/SoftwareSerial
But worry not, dynamic memory allocation comes to the rescue! For example:
SM130.h
#ifndef SM130_h
#define SM130_h
#include<Arduino.h>
#include <WConstants.h>
class SM130 {
public:
SM130();
~SM130();
void connect(int RX, int TX);
void check_for_notag();
void halt_tag();
void parse_tag();
void print_serial();
void seek_tag();
void set_flag();
private:
int rfid_flag;
int data[11];
SoftwareSerial* rfid;
};
#endif
SM130.cpp (only some methods)
SM130::SM130() : rfid(NULL) {
rfid_flag = 0;
}
void SM130::connect(int RX, int TX) {
if(!Serial.available())
{
Serial.begin(9600);
}
Serial.println("Connecting to SM130 RFID Reader...");
if (NULL != rfid)
{
delete rfid;
}
rfid = new SoftwareSerial(RX, TX)
rfid->begin(19200);
if(rfid->available())
{
rfid->println("Connected to SM130 RFID Reader!");
}
delay(10);
}
~SM130::SM130()
{
if (NULL != rfid)
{
delete rfid;
}
}
I only posted my versions of constructor, connect and destructor (good to have it for avoiding memory leaks).
Don't forget about:
Checking if rfid is not NULL (better use NULL != rfid instead of rfid != NULL, because compiler will tell you about mistakes like if (rfid = NULL))
Changing rfid. to rfid->
You can even add disconnect method, which deletes old rfid and sets pointer to NULL:
void SM130::disconnect() {
delete rfid;
rfid = NULL;
}