Arduino with SIM 900a- How can I store all incoming messages into a text file? - arduino

I have connected my Arduino Uno with SIM 900a GSM module. I want to store all my text messages that I receive on the SIM inside the GSM module to a text file continuously.
I can send SMS through the code shown below but I cannot receive and save my messages to a file. What is the correct way to do this?
#include <SoftwareSerial.h>
SoftwareSerial mySerial(9, 10);
void setup() {
mySerial.begin(9600); // Setting the baud rate of GSM Module
Serial.begin(9600); // Setting the baud rate of Serial Monitor (Arduino)
delay(100);
}
void loop() {
if (Serial.available()>0)
switch(Serial.read()) {
case 's':
SendMessage();
break;
case 'r':
RecieveMessage();
break;
}
if (mySerial.available()>0)
Serial.write(mySerial.read());
}
void SendMessage() {
mySerial.println("AT+CMGF=1"); //Sets the GSM Module in Text Mode
delay(1000); // Delay of 1000 milli seconds or 1 second
mySerial.println("AT+CMGS=\"+9779813546162\"\r"); // Replace x with mobile number
delay(1000);
mySerial.println("I am SMS from GSM Module");// The SMS text you want to send
delay(100);
mySerial.println((char)26);// ASCII code of CTRL+Z
delay(1000);
}
void RecieveMessage() {
mySerial.println("AT+CNMI=2,2,0,0,0"); // AT Command to receive a live SMS
delay(1000);
}

The Arduino cannot naturally create files on your host system, so you will need to
run an independent program on the host system which watches the serial connection and logs the messages produced by the Arduino (my recommendation)
attach some storage to the Arduino (such as an SD card shield)
have the Arduino pretend to be a keyboard and output as if it were being typed upon
Independent Program
This is the route I would recommend
easy to use and test (just check your file has the contents you want)
will not "mess up" your Arduino
can do other work and tests on system
do not need to deal with storage problems
This simple Python script may work for your needs: Serial data logging with python
This post suggests you can do it with a 1-liner under both Linux (may be the same for Mac) and Windows, but you may run into trouble with the Serial Port's baud rate. If this answer is dated or only gets some of the output (ie. a single line and then exits), you could run it in a loop or search further. You'll need to pick the right serial port as there may be a few (or just one with a different name).
Attached Storage
Many vendors will sell you a Shield for this
Adafruit Assembled Data Logging shield for Arduino (deals with filesystem automatically, nice)
SparkFun microSD Shield
generally searching "Arduino SD Card Shield" (will probably turn up cheaper versions, but they may not be of good quality, have nice drivers, tutorials, etc.)
Beware that Flash Storage can be annoying to deal with
need to eject (perhaps swap out) the card and look at it periodically to both see the results and if the results are correct
filesystems hoopla (should I use FAT, exFAT, ext2..)
ensuring the Arduino can write the filesystem (though modern shields probably do this for you, at least the Adafruit one suggested above does)
Keyboard Emulation
To start, I do not recommend doing this for the following reasons, though it's pretty neat and doesn't require any more hardware than you have.
BEWARE may make your Arduino unusable without some start gate such as waiting for a switch to be enabled (haywire inputs to computer: cannot program it)
requires total access to the computer while running (computer cannot be otherwise used)
not easier to configure than an independent logger (annoying trial and error / waiting / haywire inputs)
Official docs: https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
They have the same warning I would give
A word of caution on using the Mouse and Keyboard libraries: if the Mouse or Keyboard library is constantly running, it will be difficult to program your board. Functions such as Mouse.move() and Keyboard.print() will move your cursor or send keystrokes to a connected computer and should only be called when you are ready to handle them. It is recommended to use a control system to turn this functionality on, like a physical switch or only responding to specific input you can control. Refer to the Mouse and Keyboard examples for some ways to handle this.

Related

ESP32 Switch Between Promiscuous and STA Mode

I'm working on a project based on the ESP32 platform. The aim is to count the number of MAC addresses in the area, and transmit this information over WiFi (using an http POST request).
The first task is achieved by sniffing WIFI packets and collecting the contained addresses, following this example: https://blog.podkalicki.com/esp32-wifi-sniffer/
I believe that the code which "sniffs" the packets sets the ESP to run in promiscuous mode, and therefore I cannot connect to any AP anymore.
I've tried several solutions, first starting with timer interrupts. However this approach always led to a Core Panic and reset of the chip.
I also learnt I could use RTOS to run different tasks in parallel on the two cores of the CPU, but that didn't help to solve the problem.
void wifi_sniffer_packet_handler(void* buff, wifi_promiscuous_pkt_type_t type)
{
if (type != WIFI_PKT_MGMT)//aggiungere filtro su RSSI a questa altezza.
return;
const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buff;
const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload;
const wifi_ieee80211_mac_hdr_t *hdr = &ipkt->hdr;
//some analysis and then print the MAC address
}
void setup() {
Serial.begin(115200);
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &chUpdate, true);
timerAlarmWrite(timer, 1000000, true);//timer, arr_val, reload=true
delay(4000);
wifi_sniffer_init();
timerAlarmEnable(timer);
}
// the loop function runs over and over again forever
void loop() {
//Serial.print("inside loop");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Establishing connection to WiFi..");
}
Serial.println("Connected to network");
}
I also noticed that the code in the loop gets stuck into the while, and is restarted every time the packet handler is run (I nevere get to see "Connected to network", but i see "Establishing connection to WiFi.." several times.
Anyone can explain me what's going on? Is there a different approach to achieve this result?
Thank you.
You may have two tasks and two cores, but the ESP32 still has only one wifi chip. The way your code is written (at least, the code you shared), you'll be trying to connect to a wifi network at the same time as you're trying to run promiscuous mode. You can do only one of those things at a time.
You'll need to stop promiscuous mode before you attempt to connect to an access point. Right now your code constantly attempt to connect to a wifi access point. Use a volatile variable to store the current mode - promiscuous or connected. Change it when you need to change states. Only attempt to connect to wifi when the variable says you want to be in connected mode.
There may be some code you need to run to turn off promiscuous mode when you change states, before you connect to a wifi access point.
If you're using wifi_sniffer_init() from the example you linked to, that code isn't meant to be run in an Arduino Core application. It does some network initialization that the Arduino Core will also do. It may not be safe to do that twice (it might work, it might not... but it's definitely not intended to be done that way).
You're setting an interrupt handle chUpdate() which you didn't share. I'd bet that's the cause of your Core Panics. You can do very little in an interrupt handler. You definitely can't call most Arduino Core functions or most ESP-IDF functions. Most code isn't protected against interrupts, so the timer interrupt can occur while data structures are in an inconsistent state. Re-entering code can corrupt the data structures and cause the kind of crash you described. You're best off setting a volatile variable and waking up a task that will do the work you need done while not in the interrupt handler.
Finally, you should call WiFi.mode(WIFI_STA); before you call WiFi.begin().
For anyone confused about why you can't connect to a wifi network while in promiscuous mode - what ESP8266 and ESP32 call "promiscuous mode" is really "wifi monitor mode", which lets you monitor a wifi radio channel and see all wifi frames sent on it. They use the term "promiscuous mode" differently from the rest of the industry. Usually "promiscuous mode" means seeing all the packets being sent on the network (wifi or hardwired) that you're connected to.
I know that it's been just over a year but THANKS to the info provided by romkey I think I solved this problem within my app by calling this routine before connecting to WiFi to upload MAC data.
void end_Scan_WiFi() {
esp_wifi_set_promiscuous(false);
esp_wifi_stop();
}
Followed by this ...
WiFi.mode(WIFI_STA);
WiFi.begin(ssid,pass);

Arduino: Detect code info

Is there any way to detect the code version or any info like last updated or size of code or size of binary code?
Here is example:
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
// turn the LED on (HIGH is the voltage level)
delay(1000);
// wait for a second
digitalWrite(LED_BUILTIN, LOW);
// turn the LED off by making the voltage LOW
delay(1000);
// wait for a second
}
If I upload code to Arduino board, can I detect any info inside Arduino regarding the size of the code or the last modified time or upload time etc?
Thanks.
Compilation date is stored in the __DATE__ macro, the current system time at compilation is stored in the __TIME__ macro. Also useful may be the __FILE__ macro, which stores the filename. Reference (and other relevant macros): http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_preprocessor.Pre-defined_macros.html
There is some interesting discussion about something along these lines here:
https://github.com/arduino/Arduino/issues/5618
In that thread they're discussing ways to store the Git hash of the code at the time of the compilation/upload. If you're using Git version control that information would probably be more useful than last modified time or code size for determining which version is running on your microcontroller and being able to easily retrieve that version. I'm not sure how crazy I am about automatically doing a commit on every upload by you could always squash them later once testing is finalized. If you don't use Git, the same techniques could be adapted to adding any other version information you like and even doing automatic backups of the code at that version.
As explained by facchinm in that thread, recent versions of the Arduino IDE provide hooks throughout the build process that you can use to add additional actions. See:
https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification#pre-and-post-build-hooks-since-ide-165
The original proposal is to store the version information in EEPROM. I believe the most common way to do this is via an .eep file. A problem with this idea is that the popular Optiboot bootloader used by the Arduino Uno as well as popular 3rd party hardware packages does not support writing to EEPROM during uploading (in order to fit the bootloader in a 0.5 kB boot section). You would also need to avoid conflicts caused by use of the same EEPROM addresses by the sketch.
The other thought was to instead store it in the code itself. I guess this would be done by using a hook to automatically update a header file "library" that is included by the sketch. e.g.:
#include <VersionTracker.h>
Now how do you access that information? You could have code in the sketch that sends out that information on request or startup. A simple example:
void setup() {
Serial.begin(9600);
Serial.print(F("Filename: "));
Serial.println(F(__FILE__));
Serial.print(F("Compilation timestamp: "));
Serial.println(F(__DATE__ " " __TIME__));
}
void loop() {}
Will print this information to the Serial Monitor on startup. Of course you could use any other method of communication. This sort of thing will add some significant overhead so it would perhaps be preferable (if less beginner friendly) to download the firmware from the microcontroller and then figure out a way to find the version information from the disassembly.
The time you cannot get. The Arduino doesn't have any clock or any way to know the time.
The code size you could get if you use AvrDude to read the hex code back off the chip and then just look at the size of what you read back.

Arduino Sends Old Data Through Serial

I think my problem would best be explained with an example. Here is some Arduino Code:
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println(millis());
delay(1);
}
...and here is the output:
Now, those numbers at the beginning aren't just your regular old first-bytes-of-serial-data-are-always-messed-up numbers. Those numbers are left over from the last time I opened the serial monitor. How do I know this? Because I counted how many seconds had gone by since I last opened the serial monitor, and it all matched up.
So here's the big questioroonie,
How do I make this stop? It's breaking my java program that's supposed to read data from the Arduino's current "run instance"(I don't know the correct term), and not the last one.
There is nothing wrong with your Arduino. Remember, the USB connection is not a real RS-232 serial interface, it's simulated through USB. And that USB connection is controlled by a chip with its own buffer.
Bad news is, nothing you can do if you're using the USB cable to carry your RS-232 signals, other than to send some "filler characters" to purge the buffer. Too many buffers everywhere :) Send some terminal emulation commands like "clear the screen" and "form feed" etc. to empty the pipeline of stuff in the buffer.
Which reminds me -- we should all quit using the crummy Arduino serial monitor and be vocal about it. Instead, use TeraTerm or Putty or any other good-quality terminal emulator of your choice.
Or connect with real RS232 and an adapter and cable. My development machine has three serial ports, but that's what I do. Often computers today don't even have one handy.

SoftwareSerial example not working as expected

I recently bought an Arduino UNO to read the data outputted by my Smart Meter. The meter uses serial communication and I would like to see the values being outputted on my laptop screen. I figured I would need to use the SoftwareSerial library to read the incoming data and print that data on my screen using the hardware serial and the Serial Monitor in the Arduino IDE. To become familiar with (software) serial communication on the Arduino, I reviewed the documentation of the SoftwareSerial library. Problem is, I can't get the most basic example to work and I have been stuck on this for quite a while now. The example code is below, the example can be found here
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(57600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Goodnight moon!");
// set the data rate for the SoftwareSerial port
mySerial.begin(4800);
mySerial.println("Hello, world?");
}
void loop() { // run over and over
if (mySerial.available()) {
Serial.write(mySerial.read());
}
if (Serial.available()) {
mySerial.write(Serial.read());
}
}
As far as I understand this, the following should happen:
- Type text in Serial Monitor window.
- Serial.read() reads this data and writes it to the Software Serial.
- The Software Serial reads this data and writes it back to Serial.
- That which was written appears on the screen.
But whatever I try, nothing happens. Among things I tried to following:
- Change the baud rate for both software and hardware serial (9600 for instance).
- Tried a different SoftwareSerial library (AltSoftSerial).
- Tried different RX and TX pins for SoftwareSerial.
- Instead of Serial.write(mySerial.read());, store the result in a char first.
I'm probably missing something obvious. I would be grateful to anyone who could shed some light on this or offer an alternative way for me to read the data from my Smart Meter.
Edit
I had no wiring, because the example specified "There is no circuit for this example". I tried all three options suggested by #slash-dev, but none had the expected behaviour:
SoftwareSerial with wires connecting pin 1 to pin 10 and pin 0 to pin 11. It prints strange characters:
Goodnight moon!
Ùniÿhtÿmoÿn!ÿ
nihtmoÿttt
AltSoftSerial with wires connecting 1-8 and 0-9. First prints Goodnight moon! and then it keeps printing Ô당¥�¡Ñ�moon!.
NeoSWSerial with wires connecting 1-10 and 0-11. Same as AltSoftSerial but keeps printing Ôë‹–+ë¡Ñ�j½½¹…j.
The baud rates must be the same on Serial and mySerial.
And you don't describe the connections, so I have to ask: Did you connect a wire from pin 1 (Serial transmit) to pin 10 (mySerial receive), and another wire from pin 0 (Serial receive) to pin 11 (mySerial transmit)? Note how they are crossed.
AltSoftSerial is really the best choice, but it only works on pin 8 (RX) and pin 9 (TX), which would require connecting 8 to 1 and 9 to 0. SoftwareSerial is very inefficient, because it disables interrupts for long periods of time. This can interfere with other parts of your sketch or other libraries.
My NeoSWSerial library is another alternative. It's almost as efficient as AltSoftSerial, but it works on any two pins. It can transmit and receive at the same time (unlike SoftwareSerial), but it only works at bauds 9600, 19200 and 38400.
EDIT:
I think what you've tried is probably working ok. All the software serial libraries use interrupts for processing individual bits instead of one interrupt per character. When there are other interrupts in the system (millis() TIMER0 or Serial), the bit "calculations" can be affected. This manifests as receiving the wrong byte. Your loopback test makes it especially susceptible because the sending and receiving are synchronized (the initial receive interrupt occurs while the transmit interrupt is starting the next char).
If you just hook 0 to 1, I think it will work, because the UART is able to send and receive at the same time, and it deals with complete characters, not bits. The character interrupts do not disturb the sending or receiving of the bits.
In developing the NeoSWSerial library, I have seen this manifest the same way. I had to use two Arduinos to fully test asynchronously (i.e., not synchronized). In your case, using AltSoftSerial for the SmartMeter should work fine, and you can choose different baud rates. If you are echoing the SmartMeter characters to Serial, be sure you have a higher baud rate on Serial.
This is most likely not related to the issues now 5 years ago, but in my case I was using the Arduino IDE 2.0.0-rc5 which was not writing to the soft serial for unknown reasons. I downgraded to Arduino IDE 1.8.19 and the same serial sketch worked.

Arduino: Incoming USB serial data when USB is disabled hoses the connection

I'm writing a sketch for an Arduino Leonardo that occasionally needs to communicate bidirectionally via USB serial, and also needs to be power efficient. To save power I'd like to disable the USB when it's not needed. I can successfully use power_usb_disable() and power_usb_enable() to do this, BUT only if no data is sent to the Arduino when USB is disabled.
Here's how to reproduce the problem: I run the following sketch on the Leonardo while it's connected to a serial comms program on my computer (I've tried the Arduino serial monitor and Minicom in Linux and PuTTY in Windows). It works as expected, printing out the messages, until I type something right after the "Disabling USB..." message. Once I do that, I will receive no further data from the Leo. The funny thing is, the TX and RX LEDs continue to blink as if everything is fine. The only way to get the connection working again is to reset the board.
Now, I don't really care about dropping the incoming data when USB is disabled, that's to be expected...but I would like the serial connection to continue to work correctly once USB is enabled again.
I don't know enough about how USB serial works to know how to troubleshoot this.
#include <avr/power.h>
void setup() {
Serial.begin(9600);
delay(3000);
}
void loop() {
Serial.println("USB is enabled!");
delay(1000);
// If I send characters here, everything is fine.
Serial.println("Disabling USB...");
delay(25);
power_usb_disable();
delay(1000);
// If I send characters here, it hoses the USB connection somehow.
power_usb_enable();
delay(25);
}
I guess for now the best answer to this problem is "don't do that." I can arrange not to disable the USB if the connection is open, using the "if (Serial)" thing. So if somebody has a serial monitor open and looks as if they're about to type something, I leave USB enabled. Seems to work OK, although it doesn't address the underlying general question of how to robustly disable and re-enable USB from any state it might be in. I would still love to hear expert advice on that.

Resources