ESP32 Switch Between Promiscuous and STA Mode - arduino

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);

Related

Serial communication between esp32 and iRobot Scooba 450

I am looking to modify my Scooba 450 vacuum to make it remotely controlled.
So I searched and came across this and this.
After trying different ways, I ended up getting it to work in python, with a computer running at 57600 baud. So far, so good.
But for it to be remotely controlled, I wanted to use an ESP32, I tried a lot, but I can't communicate with the robot.
Normally, when it is charging, it returns information about its battery. So I put it on charge, and tried to read his data with the ESP32, but no information comes in.
I tried connecting it directly with a micro USB to micro USB cable, but without result.
I also of course checked that the cable is working, that data is currently being sent from the Scooba.
The program:
void setup() {
Serial.begin(57600);
}
void loop() {
while (Serial.available()){
Serial.print((char)Serial.read());
}
}
My goal would be to be able to control it from a site, but before that, I must succeed in communicating with the Scooba. I don't necessarily need to be connected to the computer to know if data is being received, because I can see if the LED on it is on.
Thanks

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

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.

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.

My Arduino Uno Wifi, stops responding to wifi

My new Arduino Uno Wifi, stops responding to wifi if left inactive. To be more specific, after 2-3 hours of no wifi usage:
I cannot access the build-in configuration page of the Arduino's wifi section
Loaded programs which use Wifi are not receiving any commands via my browser
loop() continues to run just fine
It somehow seems that the wifi section of my Uno Wifi "sleeps" after some arbitrary interval.
Using code to periodically reset the board (by sending HIGH to the reset pin of the board) did not solve the problem. As soon as the reset takes place, loop() starts executing just fine, but wifi connection is still impossible to obtain.
Things I usually do to gain access to my board AFTER wifi is lost:
Hard reset the board (unplug power and plug it again) -> almost always works
Try to access arduino from several different wifi devices hoping that the board somehow "wakes up" -> occasionally works but only after 4 or 5 minutes (sometimes hours) of failed attempts
My router seems to be fine. Another web server which I have set up in a wifi-connected laptop has had no hiccups (even after a long time of inactivity). Moreover I've never had any connection problems with my router so far.
This is giving me a hard time! Could anybody be of any help?
Is my Arduino Uno faulty?
Many thanks in advance
George
Here's my configuration:
Arduino Uno Wifi Developer edition (built-in wifi support)
Arduino IDE 1.8.0 (I'm using the Linux version installed on Ubuntu 12.04 )
I have already connected my arduino to my home network and gave it a static IP 192.168.2.50
WIFI mode: STA
Wifi channel: 1
SLIP status enabled
MQTT status disabled/disconnected
code:
int i=0;
void setup() {
pinMode(13,OUTPUT);
}
void loop() {
if (i==1){
digitalWrite(13, HIGH);
i=0;
}
else{
digitalWrite(13,LOW);
i=1;
}
delay(1000);
}
It seems that I have been a victim of an extreme ambiguity caused by the .org fork of arduino.
Arduino.cc and Arduino.org boards are NOT 100% compatible with each other.
To be more specific, the examples that come with the IDE (and are based on the the wifi shield of arduino.cc) DO NOT function with aruduino-uno-wifi (the one with the embedded wifi section)
Apart from that, it seems that arduino-uno-wifi has firmware that is way behind the arduino.cc (in terms of features as well as code quality). This has frustrated several users as you can see here:
Issue 2: Rename this fork and use less confusing versioning
Issue 10: Please stop doing this !
Issue 6: Remove old licenses from sample code comments and take credit for everything
If you are interested of an arduino.org view of things visit here:
The full story
All of the above is information which I wish I had when ordering my new ardnino-uno-wifi board.
Moreover it is relevant with the question I've asked, since it indicates that my problem is most probably a bug of the uno-wifi board, so I should file a bug report (and keep hoping) instead of trying to fix my code.

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