I have this question because I was standing still and I don't know what to do;)
I would like to write to Flash stm32 using arduino library latitude and longitude of 3 European capitals;)
I am a layman when it comes to programming. Below is my code.
Could someone please help me how to properly write these values in flash. Then I would like to read them, but first I want to focus on writing to flash.
I use this library
https://github.com/khoih-prog/FlashStorage_STM32
#include <FlashStorage_STM32.h>
const int WRITTEN_SIGNATURE = 0xBEEFDEED;
// Create a structure that is big enough to contain a latitude
// and a longitude. The "valid" variable is set to "true" once
// the structure is filled with actual data for the first time.
typedef struct
{
int index[3];
char latitude[100];
char longitude[100];
} Capitals;
//data
int data11 = 52,211233;
int data12 = 4,532122;
int data21 = 38,024321;
int data22 = 23,443456;
int data31 = 38,024321;
int data32 = 23,443456;
void setup()
{
Serial.begin(115200);
while (!Serial);
delay(200);
Serial.print(F("\nStart StorelatitudeAndlongitude on ")); Serial.println(BOARD_NAME);
Serial.println(FLASH_STORAGE_STM32_VERSION);
Serial.print("EEPROM length: ");
Serial.println(EEPROM.length());
// Check signature at address 0
int signature;
// Create a "Capitals" variable and call it "owner"
uint16_t storedAddress = 0;
Capitals owner;
EEPROM.get(storedAddress, signature);
Serial.println("EEPROM is empty, writing WRITTEN_SIGNATURE and some example data:");
EEPROM.put(storedAddress, WRITTEN_SIGNATURE);
// ...in this case we ask for user data.
Serial.setTimeout(30000);
Serial.print("Insert your latitude : ");
String latitude = Serial.readStringUntil('\n');
Serial.println(latitude);
Serial.print("Insert your longitude : ");
String longitude = Serial.readStringUntil('\n');
Serial.println(longitude);
// Fill the "owner" structure with the data entered by the user...
latitude.toCharArray(owner.latitude, 100);
longitude.toCharArray(owner.longitude, 100);
// ...and finally save everything into emulated-EEPROM
EEPROM.put(storedAddress + sizeof(signature), owner);
// Print a confirmation of the data inserted.
Serial.print("<< Your latitude: "); Serial.print(owner.latitude);
Serial.print(". Your longitude: "); Serial.print(owner.longitude);
Serial.println(" >> have been saved. Thank you!");
}
void loop()
{
// Do nothing...
}
Thank you in advance for your help
Related
I have the following code:
#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEAdvertisedDevice.h>
static void log(String message) {
Serial.println(message);
}
const char* deviceName = "BLEScanner";
BLEScan* pBLEScan;
void setup() {
Serial.begin(115200);
log("Setup!");
BLEDevice::init(deviceName);
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // less or equal setInterval value
}
void loop() {
log("Listing BLE Sensors");
BLEScanResults foundSensors = pBLEScan->start(30, false);
int count = foundSensors.getCount();
for (int i = 0; i < count; i++) {
BLEAdvertisedDevice bleSensor = foundSensors.getDevice(i);
String sensorName = bleSensor.getName().c_str();
String address = bleSensor.getAddress().toString().c_str();
log(address + " " + sensorName);
}
log("Sleeping");
sleep(10);
}
And when running it I get the following output:
Setup!
Listing BLE Sensors
00:09:b0:09:e7:ca
41:59:8f:07:ec:96
ac:5d:5c:e1:72:89 LM0845
c4:7c:8d:6a:36:cf Flower care
c4:7c:8d:6a:45:6b Flower care
c4:7c:8d:6a:46:2c Flower care
de:d5:2a:8e:1e:fd Tile
Sleeping
Listing BLE Sensors
00:09:b0:09:e7:ca
41:59:8f:07:ec:96
ac:5d:5c:e1:72:89
dc4:7c:8d:6a:36:cf
dc4:7c:8d:6a:45:6b
dc4:7c:8d:6a:46:2c
de:d5:2a:8e:1e:fd Tile
Sleeping
Listing BLE Sensors
00:09:b0:09:e7:ca
41:59:8f:07:ec:96
ac:5d:5c:e1:72:89
c4:7c:8d:6a:36:cf
dc4:7c:8d:6a:45:6b
dc4:7c:8d:6a:46:2c
de:d5:2a:8e:1e:fd Tile
... and so on
For some reason I only get the names of some of the devices the first time, is this a known error and what can be done about it?
I have tried to put a pBLEScan->clearResults(); before I start a scan but that did not help.
I'm using an ESP32 Adafruit feather.
The only solution I have found is to put the BLEDevice::init(deviceName); inside the loop and then run BLEDevice::deinit(); before sleep!
I'm still learning the ropes so forgive me if the answer to this is obvious. I'm using the Arduino Uno and a RC522 RFID card reader. My aim is to scan a card on the reader and have the I2C OLED display show me the name of the person who has scanned their card. This is the code for the program I'm using -
#include <U8glib.h>
#include <LiquidCrystal.h>
#include <RFID.h>
#include <SPI.h>
#define SS_PIN 10
#define RST_PIN 9
RFID rfid(SS_PIN, RST_PIN);
int serNum[5];
String cardno;
int interval = 15000; // millisec
long now = 0;
long lasttime = millis();
// change Reader ID to your name
String readerID = "CCE3050";
void setup() {
Serial.begin(9600);
SPI.begin();
rfid.init();
}
void loop() {
now = millis();
if (now > lasttime + interval) {
lasttime = now;
Serial.print(readerID);
Serial.print(":");
Serial.println("I am alive");
}
if (rfid.isCard()) {
if (rfid.readCardSerial()) {
lasttime = now;
cardno = String(rfid.serNum[0]) +
String(rfid.serNum[1]) +
String(rfid.serNum[2]) +
String(rfid.serNum[3]) +
String(rfid.serNum[4]);
Serial.print(readerID);
Serial.print(":");
Serial.println(cardno);
}
}
delay(5000);
}
So far, each time a card is tagged, the card number is displayed on the serial monitor. However, I would like to assign a name to the card and display that name on the OLED whenever the card is tagged onto the reader. Is there a way to do this?
I suggest creating a struct to hold an id and its associated name.
typedef struct {
String id;
String name;
} User;
Create an array to hold multiple instances of the struct.
User users[MAX_USER_NUM]; // define the size
User user1 = {"123", "A"}; // {"id", "name"}
users[0] = user1;
User user2 = {"234", "B"};
users[1] = user2;
User user3 = {"345", "C"};
users[2] = user3;
You can then retrieve a user name by passing an id to a function like this.
String lookup(String id) {
for (int i = 0; i < MAX_USER_NUM; i++) {
if (users[i].id == id) {
return users[i].name;
}
}
return "";
}
An easy way to do it would be store a json with in SPIFF.
The structure of the JSON could be like:-
{[{"card_no: 123, "name": "Jhon"},{ "card_no": 124, "name": "Sam"}]}
The advantage of using SPIFF is that you can retrieve the data even after you reboot.
After you get the card number you can find the card number in the Json data and show the name
Appreciate your time.
I am trying to convert "String" read from serial port in serialEvent() of Arduino IDE to integer values with exact representation.
For eg, if String myString = 200 then int myInt should be 200.
I have been somewhat successful but unable to convert String to exact int representation beyond 255.
Solutions I have tried:
1) used .toInt() function in Arduino.
2) used "atoi" and "atol" functions.
3) Serial.parseInt() in loop().
All of these methods start recounting from 0 after every 255 values.
I can't use parseInt since it only works inside loop(). My application requires to store variable value permanently until another value is given through port. For this Arduino Due's flash memory has been used.
The memory storing code seems to work only inside serialEvent().
Code snippet is as below:
#include <stdlib.h>
#include <DueFlashStorage.h>
DueFlashStorage memory;
String x = " ";
int x_size;
int threshold;
void setup(){
Serial.begin(115200);
}
void loop{
Serial.println(memory.read(0));
}
void serialEvent(){
while(Serial.available()){
x = Serial.readStringUntil('\n');
x_size = x.length();
char a[x_size+1];
x.toCharArray(a, x_size+1);
threshold = atoi(a);
memory.write(0, threshold);
}
}
1) Function .toInt() returns LONG and you want INT (I don't know why honestly but it is in documentation)... you need to cast it like this (tried on Arduino ATMEGA and it worked):
#include <stdlib.h>
String x = "1000";
int x_ = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
x_ = (int) x.toInt();
Serial.println(x_);
delay(1000);
}
2) I’m not professional ... but serilEvent() is really old way of doing things and it isn't recommended to use it. You can do it "manually" in the loop() function.
You're only converting 1 character a time, that's why the limit is 255.
If you're not doing anything else, you could stay in a serial.read-loop until all characters are read. For example:
void loop() {
if(Serial.available()) {
byte count = 0;
char number[10]; // determine max size of array
bool wait = true;
while(wait) { // stay in this loop until newline is read
if(Serial.available()) {
number[count] = Serial.read();
if (number[count] == '\n') {
wait = false; // exit while loop
}
count++;
}
}
int threshold = atoi(number);
memory.write(0, threshold);
}
}
For the lack of a good function in Arduino IDE for char/String type to int type conversion (has a limit of 255), I wrote my own conversion code which seems to work perfectly.
int finalcount=0;
void setup(){
Serial.begin(115200);
}
void loop(){
if(Serial.available()) {
int count = 0;
char number[5]; // determine max size of array as 5
bool wait = true;
while(wait) { // stay in this loop until newline is read
if(Serial.available()) {
number[count] = Serial.read();
if (number[count] == '\n') {
finalcount = count; //max array size for integer; could be less than 5
wait = false; // exit while loop
}
count++;
}
}
int val[finalcount]; //array size determined for integer
int placeValue;
int finalval[finalcount];
int temp=0;
int threshold;
for(int i = 0; i<finalcount; i++){
val[i] = (int)number[i]-48; //convert each char to integer separately
placeValue = pow(10,(finalcount-1)-i); //calculate place value with a base of 10
finalval[i] = val[i]*placeValue; //update integers with their place value
temp += finalval[i] ; //add all integers
threshold = temp; //resulting number stored as threshold
}
Serial.println(threshold); //prints beyond 255 successfully !
}
}
I solved the problem using highByte and lowByte functions of Arduino. Works flawlessly.
#include <DueFlashStorage.h>
DueFlashStorage m;
byte a1,a2;
int val;
void setup() {
Serial.begin(115200); //start the serial communication
}
void loop()
{
if (Serial.available()>0)
{
val = Serial.parseInt(); //read the integer value from series
if(val>0){
a1 = highByte(val); //get the higher order or leftmost byte
a2 = lowByte(val); //get the lower order or rightmost byte
m.write(0,a1); //save in arduino due flash memory address 0
m.write(1,a2); //save in arduino due flash memory address 1
}
int myInteger;
myInteger = (m.read(0)*256)+m.read(1); //convert into the true integer value
Serial.println(myInteger);
}
I want to do project which will use GPS & GSM module, use Arduino, take data from GPS(GY-GPS/NEO6MV2) and send by GSM(SIM900 GSM/GPRS Module ) to my phone. I am using separate GPS module
I try this code but still have problem.
#include <SoftwareSerial.h>
#include "SIM900.h"
#include <TinyGPS.h>
#include "sms.h"
SMSGSM sms;
TinyGPS gps;
SoftwareSerial ss(4, 3);
SoftwareSerial SIM900(7, 8);
static void smartdelay(unsigned long ms);
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);
String strL, strN, message, textForSMS;
char charL[10], charN[10], text[200];
int m = 1;
boolean started = false;
void setup()
{
Serial.begin(9600);
ss.begin(9600);
gsm.begin(9600);
}
void loop()
{
float flat, flon;
unsigned long age, date, time, chars = 0;
unsigned short sentences = 0, failed = 0;
gps.f_get_position(&flat, &flon, &age);
textForSMS = "Moosa Home"; //testing gps from here
Serial.println(textForSMS);
Serial.println(flat, 6);
Serial.println(flon, 6);
Serial.print("longitude: ");
print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
Serial.println("");
Serial.print("latitude : ");
print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
smartdelay(1000);
Serial.println(""); //till here
delay(1000);
if (m == 5) //send sms on third reading
{
Serial.println("XXXXXXXXX"); //to check whether 'if' works
dtostrf(flat, 4, 6, charL);
for (int i = 0; i < 10; i++)
{
strL += charL[i];
}
dtostrf(flon, 4, 6, charN);
for (int i = 0; i < 10; i++)
{
strN += charN[i];
}
message = "Home";
message = message + "/nLat: ";
message = message + strL;
message = message + "/nLon: ";
message = message + strN;
message.toCharArray(text, 250);
Serial.println(text);
if (sms.SendSMS("+999999999999999", text))
{
Serial.println("\nSMS sent OK.");
}
else
{
Serial.println("\nError sending SMS.");
}
do {} while (1);
}
m++;
}
static void smartdelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
static void print_float(float val, float invalid, int len, int prec)
{
if (val == invalid)
{
while (len-- > 1)
Serial.print('*');
Serial.print(' ');
}
else
{
Serial.print(val, prec);
int vi = abs( val);
int flen = prec + (val < 0.0 ? 2 : 1); // . and -
flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i = flen; i < len; ++i)
Serial.print(' ');
}
smartdelay(0);
}
static void print_str(const char *str, int len)
{
int slen = strlen(str);
for (int i = 0; i < len; ++i)
Serial.print(i < slen ? str[i] : ' ');
smartdelay(0);
}
I receive SMS
Home/nLat:1000.00000/nLon:1000.00000`
where is my mistake in this code?
I am sure Gps & gsm work properly
Using TinyGPS on SoftwareSerial + a loop() structure using delay(1000), has very low odds of working. The m counter is really useless here, because loop() will execute 1000's of times while the GPS characters are arriving. And doing a get_position is useless, because you may not have any GPS data yet.
Basically, loop() should be constantly running, without delays. When something important happens (like getting all of a GPS sentence, or enough time has passed), that's when you do your other work (like send an SMS message). The TinyGPS smartDelay is not smart.
You should restructure the loop to look more like this example from the NeoGPS library. All the non-GPS work should be performed where the digitalWrite is in that example (line 62). That's where you would take the time to send an SMS.
The TinyGPS examples would require a complete rewrite to do what you want. They are fine by themselves, but it is difficult to extend them to do other things, like send an SMS. As I said, the loop structure must change.
I suggest taking a look at the NeoGPS library I wrote, as the examples are more robust. The library also uses much less RAM and CPU time, but that isn't a big problem if all you need to do is send an SMS message. If you do want to try it, be sure to review the default SoftwareSerial choice.
If you get the simple NMEAblink.ino example to work, I would suggest trying NMEA.ino. Then insert your code into the doSomeWork function. Most of what you have in loop needs to go in the doSomeWork function, which is called only when a complete RMC sentence is received.
Regardless of which library you use, you also need to check whether the data is valid. What if your GPS isn't receiving any satellites? It may still send an RMC sentence, but there won't be any lat/lon data. You probably shouldn't send an SMS if the location field is not valid.
#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"
SMSGSM sms;
boolean started=false;
int count = 0;
void setup()
{
pinMode(5, INPUT); // input pin for switch
Serial.begin(9600);
if (gsm.begin(2400))
{
Serial.println("\nstatus=READY");
started=true;
}
else Serial.println("\nstatus=IDLE");
delay(1000);
}
void loop()
{
if (digitalRead(5)==1)
{
delay(500);
if (digitalRead(5)==1)
{
count = count+1;
/*if(started)
{
if (sms.SendSMS("+12345678", "ALARM"))
Serial.println("\nSMS sent OK");
}*/
Serial.println("Count = ");
Serial.println(count);
readtime();
Serial.println(content);
}
}
else
{
Serial.println("Normal");
}
}
I use sim 900 with arduino to detect change of input pin 5 and then ALARM to user. I have a few question that need your help
How can I know which pin that sim 900 use to communicated for sent sms? I use jumper at D2 and D3. Did it use these two pins? because in my program I use an .h include file which I didn't know detail inside it.
How can I read date and time data from RTC in sim 900 module and store in a variable and use them for data logger later? I know that if I have already set date and time in RTC, it can be read by "AT+CCLK?" and it return date and time data. But how can I use this command in my program?
I found this code and work for me. First you ask for time and then expect answers and parse it.
const char* const SIM900::getTimeStamp(){
Serial2.print("AT+CCLK?"); //SIM900 AT command to get time stamp
Serial2.print(13,BYTE);
delay(2000);
if (Serial2.available()>0){
int i = 0;
while (Serial2.available()>0){
timeStamp[i]=(Serial2.read());
i++;
}
}
int years = (((timeStamp[25])-48)*10)+((timeStamp[26])-48);
int months = (((timeStamp[22])-48)*10)+((timeStamp[23])-48);
int days = (((timeStamp[19])-48)*10)+((timeStamp[20])-48);
int hours = (((timeStamp[28])-48)*10)+((timeStamp[29])-48);
int mins = (((timeStamp[31])-48)*10)+((timeStamp[32])-48);
int secs = (((timeStamp[34])-48)*10)+((timeStamp[35])-48);
//YOUR CODE HERE
}