I'm trying to set a unique id to each esp32 automatically. Before I was programming the devices using the ESP-IDF Framework that provides the method
esp_efuse_mac_get_default() this will return a 8 byte value unique over all devices I had my hands on.
In the arduino ide all I see is the ESP.getEfuseMac() method. This only returns 6 bytes and is the same for all devices of the same batch (?).
Is there any way I can get a 8 byte UUID on a ESP32?
Libraries like ArduinoUniqueID also use the ESP.getEfuseMac() and thus are not usable.
getEfuseMac returns a 64 bit integer.
uint64_t EspClass::getEfuseMac(void)
{
uint64_t _chipmacid = 0LL;
esp_efuse_mac_get_default((uint8_t*) (&_chipmacid));
return _chipmacid;
}
It should return it's MAC address which is unique to all esp.
On the ESP32 both ESP.getEfuseMac() and ESP.getChipId() returns the same MAC address.
Test it with:
Serial.printf("\nCHIP MAC: %012llx\n", ESP.getEfuseMac());
Serial.printf("\nCHIP MAC: %012llx\n", ESP.getChipId());
Or you could do this:
uint32_t low = ESP.getEfuseMac() & 0xFFFFFFFF;
uint32_t high = ( ESP.getEfuseMac() >> 32 ) % 0xFFFFFFFF;
uint64_t fullMAC = word(low,high);
Serial.printf("Low: %d\n",low);
Serial.printf("High: %d\n",high);
Serial.printf("Full: %d\n",fullMAC);
You can also use IDF functions in Arduino because it was built on it.
Check this:
void print_mac(const unsigned char *mac) {
printf("%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
}
void macTest(){
unsigned char mac_base[6] = {0};
esp_efuse_mac_get_default(mac_base);
esp_read_mac(mac_base, ESP_MAC_WIFI_STA);
unsigned char mac_local_base[6] = {0};
unsigned char mac_uni_base[6] = {0};
esp_derive_local_mac(mac_local_base, mac_uni_base);
printf("Local Address: ");
print_mac(mac_local_base);
printf("\nUni Address: ");
print_mac(mac_uni_base);
printf("MAC Address: ");
print_mac(mac_base);
}
void setup(){
Serial.begin(115200);
delay(500);
macTest();
}
Related
I have an Arduino Nano 33 iot that outputs data via Serial at 38400 baud, connected via USB. Setup starts with Serial.Begin. The Raspberry Pi 4, running Raspian buster is set up to receive the data. It can see the correct port, /dev/ttyACM0, but nothing comes in.
I even installed the correct Arduino IDE and SAMD board package on the Raspberry Pi. It still does not find it until after the IDE uploads the replacement sketch and the CPU is reset. The IDE can grab the serial number and board type though. I can then exit out of the IDE and the Arduino is still pumping out serial to the Raspberry Pi.
The only other way to make it work is by pressing the reset button on the Arduino every time a reboot is done on the Raspberry Pi. Serial was tested on the Pi using screen.
Neither of these options are convenient. What am I missing?
/*
Connects via I2C to a CMPS14, outputs NMEA0183 HDM sentences via Serial (38400 baud)
By James Henderson, 2014, adapted to output NMEA sentences by Ian Van Schaick
*/
#include <Keyboard.h>
#include <Wire.h>
#define CMPS14_ADDRESS 0x60 // Address of CMPS14 shifted right one bit for arduino wire library
#define ANGLE_8 1 // Register to read 8bit angle from
unsigned char high_byte, low_byte, angle8;
signed char pitch, roll;
float angle16;
int fine;
float bearingH; // Holds whole degrees of bearing
float bearingL; // Holds decimal digits of bearing
int bearing;
char nbsp;
char mystring[25];
char mystring2[25];
char mystring3[25];
int software;
int cal;
unsigned int _last_status;
uint8_t checksum(char *s)
{
uint8_t c = 0;
while (*s)
c ^= *s++;
return c;
}
void CMPS14_eraseProfil()
{
Wire.beginTransmission(CMPS14_ADDRESS);
Wire.write(0x00);
Wire.write(0xE0);
_last_status = Wire.endTransmission();
delay(20); // 20ms delay after each of the three bytes send
Wire.beginTransmission(CMPS14_ADDRESS);
Wire.write(0x00);
Wire.write(0xE5);
_last_status = Wire.endTransmission();
delay(20); // 20ms delay after each of the three bytes send
Wire.beginTransmission(CMPS14_ADDRESS);
Wire.write(0x00);
Wire.write(0xE2);
_last_status = Wire.endTransmission();
delay(20); // 20ms delay after each of the three bytes send
}
//Correct heading for known deviation
int DeviationCorrect(int Head)
{
return 0;
}
void setup() {
Serial.begin(38400); // Start serial port
Wire.begin();
nbsp = 32;
// CMPS14_eraseProfil();
}
void loop() {
Wire.beginTransmission(CMPS14_ADDRESS); //starts communication with CMPS14
Wire.write(ANGLE_8); //Sends the register we wish to start reading from
Wire.endTransmission();
// Request 5 bytes from the CMPS14
// this will give us the 8 bit bearing,
// both bytes of the 16 bit bearing, pitch and roll
Wire.requestFrom(CMPS14_ADDRESS, 26);
while (Wire.available() < 26); // Wait for all bytes to come back
// software = Wire.read();
// Serial.print("Version: ");
// Serial.println(software);
angle8 = Wire.read(); // Read back the 5 bytes
high_byte = Wire.read();
low_byte = Wire.read();
pitch = Wire.read();
roll = Wire.read();
// int i = 6;
// while (i <= 25) {
// Wire.read();
// i++;
// }
//
// cal = Wire.read();
// Serial.print("Cal: ");
// Serial.println(cal);
bearing = ((high_byte << 8) + low_byte) / 10;
fine = ((high_byte << 8) + low_byte) % 10;
byte data[128] = "$HCHDM,";
data[8] = bearing;
// int deviation = 0;
//DeviationCorrect(bearing);
// bearing = bearing;
//+ deviation;
//Print out NMEA 0183 string HDM
snprintf(mystring, sizeof(mystring), "$HCHDM,%d.%d,M", bearing , fine);
uint8_t crc = checksum(mystring + 1);
Serial.print(mystring);
Serial.print("*");
if (crc < 16) Serial.print("0");
Serial.println(crc, HEX);
//Print out NMEA 0183 string XDR for Pitch
snprintf(mystring2, sizeof(mystring2), "$HCXDR,A,%d,D,PITCH", pitch);
uint8_t crc2 = checksum(mystring2 + 1);
Serial.print(mystring2);
Serial.print("*");
if(crc2 < 16) Serial.print("0");
Serial.println(crc2, HEX);
//Print out NMEA 0183 string XDR for Roll/Heel
snprintf(mystring3, sizeof(mystring3), "$HCXDR,A,%d,D,ROLL", roll);
uint8_t crc3 = checksum(mystring3 + 1);
Serial.print(mystring3);
Serial.print("*");
if(crc3 < 16) Serial.print("0");
Serial.println(crc3, HEX);
delay(100);
}
I'm trying to get the following project running:
https://github.com/kalanda/esp8266-sniffer
The project is about Probe Frame / Probe Request. It let's a simple ESP8266 act like a WLAN Router, and collect all incoming Probe Frames. Every Probe Frame should include the MAC address of the device, and one SSID of it's saved networks. That's it.
I have copied the code of the project on my ESP8266.
I have 3 different smartphones laying around.
So now, when I look in the Serial Monitor, I should see all the packages from my 3 smartphones, every package should include the MAC address of the smartphone, and also one of the saved SSID's, which it was connected to in the past.
I see everything, except for the SSID's.
I can see the Probe Frames, coming from my different smartphones, but the SSID's are just blank.
Anyone has a idea?
Here is the complete code of the project.
Also, I have attached a screenshot of my Serial Monitor output. I have just painted the MAC addresses of my smartphones green. So as you can see, no SSIDs.
I'm very thankful for EVERY help or idea!
Thanks in advance,
EMHA.
SCREENSHOT OF SERIAL MONITOR OUTPUT
#include <Arduino.h>
extern "C" {
#include <user_interface.h>
}
#define DATA_LENGTH 112
#define TYPE_MANAGEMENT 0x00
#define TYPE_CONTROL 0x01
#define TYPE_DATA 0x02
#define SUBTYPE_PROBE_REQUEST 0x04
struct RxControl {
signed rssi:8; // signal intensity of packet
unsigned rate:4;
unsigned is_group:1;
unsigned:1;
unsigned sig_mode:2; // 0:is 11n packet; 1:is not 11n packet;
unsigned legacy_length:12; // if not 11n packet, shows length of packet.
unsigned damatch0:1;
unsigned damatch1:1;
unsigned bssidmatch0:1;
unsigned bssidmatch1:1;
unsigned MCS:7; // if is 11n packet, shows the modulation and code used (range from 0 to 76)
unsigned CWB:1; // if is 11n packet, shows if is HT40 packet or not
unsigned HT_length:16;// if is 11n packet, shows length of packet.
unsigned Smoothing:1;
unsigned Not_Sounding:1;
unsigned:1;
unsigned Aggregation:1;
unsigned STBC:2;
unsigned FEC_CODING:1; // if is 11n packet, shows if is LDPC packet or not.
unsigned SGI:1;
unsigned rxend_state:8;
unsigned ampdu_cnt:8;
unsigned channel:4; //which channel this packet in.
unsigned:12;
};
struct SnifferPacket{
struct RxControl rx_ctrl;
uint8_t data[DATA_LENGTH];
uint16_t cnt;
uint16_t len;
};
// Declare each custom function (excluding built-in, such as setup and loop) before it will be called.
// https://docs.platformio.org/en/latest/faq.html#convert-arduino-file-to-c-manually
static void showMetadata(SnifferPacket *snifferPacket);
static void ICACHE_FLASH_ATTR sniffer_callback(uint8_t *buffer, uint16_t length);
static void printDataSpan(uint16_t start, uint16_t size, uint8_t* data);
static void getMAC(char *addr, uint8_t* data, uint16_t offset);
void channelHop();
static void showMetadata(SnifferPacket *snifferPacket) {
unsigned int frameControl = ((unsigned int)snifferPacket->data[1] << 8) + snifferPacket->data[0];
uint8_t version = (frameControl & 0b0000000000000011) >> 0;
uint8_t frameType = (frameControl & 0b0000000000001100) >> 2;
uint8_t frameSubType = (frameControl & 0b0000000011110000) >> 4;
uint8_t toDS = (frameControl & 0b0000000100000000) >> 8;
uint8_t fromDS = (frameControl & 0b0000001000000000) >> 9;
// Only look for probe request packets
if (frameType != TYPE_MANAGEMENT ||
frameSubType != SUBTYPE_PROBE_REQUEST)
return;
Serial.print("RSSI: ");
Serial.print(snifferPacket->rx_ctrl.rssi, DEC);
Serial.print(" Ch: ");
Serial.print(wifi_get_channel());
char addr[] = "00:00:00:00:00:00";
getMAC(addr, snifferPacket->data, 10);
Serial.print(" Peer MAC: ");
Serial.print(addr);
uint8_t SSID_length = snifferPacket->data[25];
Serial.print(" SSID: ");
printDataSpan(26, SSID_length, snifferPacket->data);
Serial.println();
}
/**
* Callback for promiscuous mode
*/
static void ICACHE_FLASH_ATTR sniffer_callback(uint8_t *buffer, uint16_t length) {
struct SnifferPacket *snifferPacket = (struct SnifferPacket*) buffer;
showMetadata(snifferPacket);
}
static void printDataSpan(uint16_t start, uint16_t size, uint8_t* data) {
for(uint16_t i = start; i < DATA_LENGTH && i < start+size; i++) {
Serial.write(data[i]);
}
}
static void getMAC(char *addr, uint8_t* data, uint16_t offset) {
sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", data[offset+0], data[offset+1], data[offset+2], data[offset+3], data[offset+4], data[offset+5]);
}
#define CHANNEL_HOP_INTERVAL_MS 1000
static os_timer_t channelHop_timer;
/**
* Callback for channel hoping
*/
void channelHop()
{
// hoping channels 1-13
uint8 new_channel = wifi_get_channel() + 1;
if (new_channel > 13) {
new_channel = 1;
}
wifi_set_channel(new_channel);
}
#define DISABLE 0
#define ENABLE 1
void setup() {
// set the WiFi chip to "promiscuous" mode aka monitor mode
Serial.begin(115200);
delay(10);
wifi_set_opmode(STATION_MODE);
wifi_set_channel(1);
wifi_promiscuous_enable(DISABLE);
delay(10);
wifi_set_promiscuous_rx_cb(sniffer_callback);
delay(10);
wifi_promiscuous_enable(ENABLE);
// setup the channel hoping callback timer
os_timer_disarm(&channelHop_timer);
os_timer_setfn(&channelHop_timer, (os_timer_func_t *) channelHop, NULL);
os_timer_arm(&channelHop_timer, CHANNEL_HOP_INTERVAL_MS, 1);
}
void loop() {
delay(10);
}
The probe requests that you are recording most probably do not even contain an SSID.
Directed probes (targetting a specific SSID) came somewhat out of fashion, mainly for privacy reasons (clients are revealing the SSID they are looking for). What you are seeing are broadcast probe requests. Basically the same thing, but difference is that they do contain an SSID. All access points that receive such probe request frames reply with a probe response, this way allowing the client to aggregate a list of networks in range.
Directed probe requests nowadays are only sent just right before a (re-) connection is established. So maybe it helps if you disconnect/reconnect some clients from the Wi-Fi network to test your code?
I am trying to use Arduino Mega 2560 for extending I/Os of RPi3 with PWM and Analog Inputs. Infact I am not using RPi3 GPIO pins at all as maintaining two voltages for inputs 3.3 and 5 V is difficult.
Basically, I am trying to:
send an Array from RPi3 to set the outputs in Arduino and
send an Array from Arduino to RPi3 giving the status of Inputs.
Some values in the array could go as high as 10000.
I have been able to achieve the Number 1 above without the values higher than 255.
Python Code
bus = smbus.SMBus(1)
address = 0x06
def writeNumber(value):
bus.write_i2c_block_data(address, 1, [5,0,1,255, 6]) #dummy array as of now. This can go upto 50 values
return -1
def readNumber():
# number = bus.read_byte(address)
data_received_from_Arduino = bus.read_byte(address)
for i in data_received_from_Arduino:
print(i)
return number
while i1:
writeNumber(1)
readNumber()
Arduino Code
#include <Wire.h>
#define SLAVE_ADDRESS 0x06
int number[50] = {0};
int inputs[100] = {0};
int state = 0;
int p=0;
void setup() {
pinMode(13, OUTPUT);
Serial.begin(9600); // start serial for output
// initialize i2c as slave
Wire.begin(SLAVE_ADDRESS);
// define callbacks for i2c communication
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
Serial.println('Ready!');
}
void loop() {
//delay(1);
}
// callback for received data
void receiveData(int byteCount){
Serial.println(byteCount);
int p=0;
while(Wire.available()) {
number[p] = Wire.read();
p++;
}
for(int k=0; k < 5; k++) {
Serial.print( k);
Serial.print( ":");
Serial.println(number[k]);
}
}
// callback for sending data
void sendData(){
for(int k=0; k < 56;k++) {
inputs[k] = digitalRead(k);
Serial.print( k ); Serial.print(" : "); Serial.print(inputs[k]);
Serial.println(digitalRead(k));
}
Wire.write( inputs,56);
}
Can somebody guide? Does anyone know a sample Git for achieve the above. I can build it up for my application even if the sample is for a small array.
I have been playing around experimenting with sending and receiving four 16-bit numbers from a Raspberry Pi to an Arduino over I2C and got the following working.
Be aware that I am no expert in SMBus or I2C and I don't know if there are easier ways to do this. I am happy to retract my answer if anyone knows better!
Here's the code for the Raspberry Pi, it just sends four 16-bit numbers 100, 200, 1000, 10000 and then reads them back.
#!/usr/bin/env python3
from smbus import SMBus
from time import sleep
bus = SMBus(1)
address = 0x08
def split(v):
"""Split 16-bit value into low and high bytes"""
lobyte = v & 0xff
hibyte = (v >> 8) & 0xff
return lobyte, hibyte
def join(lo,hi):
return lo | (hi << 8)
def Transmit():
"""Send 100, 200, 1000, 10000 on I2C"""
a,b = split(100)
c,d = split(200)
e,f = split(1000)
g,h = split(10000)
bus.write_i2c_block_data(address, a,[b, c, d, e, f, g, h])
def Receive():
block = bus.read_i2c_block_data(address, 0)
i = join(block[0],block[1])
j = join(block[2],block[3])
k = join(block[4],block[5])
l = join(block[6],block[7])
print("{} {} {} {}".format(i,j,k,l))
Transmit()
sleep(1)
Receive()
On the Arduino side, I just read four 16-bit numbers from I2C, store them in an array and increment each one. When a read request comes in, I send back the four incremented numbers:
#include <Wire.h>
const int address= 8;
#define N 4
// Last four 16-bit values we received
int16_t values[N];
void setup() {
Serial.begin(9600);
Serial.print("Starting on i2c address:");
Serial.println(address,DEC);
Wire.begin(address);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
}
void loop() {
delay(100);
}
// callback for when data are received
void receiveEvent(int nBytes) {
Serial.print("Received: ");
Serial.println(nBytes);
if(nBytes != 2 *N){
Serial.print("I was expecting 8 bytes");
return;
}
unsigned char *p = (unsigned char *)&values;
for(int i=0;i<2*N;i++){
*p++ = Wire.read();
}
// Increment all the values we received
for(int i=0;i<N;i++){
values[i]++;
}
}
// Callback for when data are read
void requestEvent() {
Serial.println("Data requested");
// Send back
Wire.write((const uint8_t*)&values, N*2);
}
When I run the Python code on the Raspberry Pi, I get:
./i2c.py
101 201 1001 10001
The easiest way to communicate with raspberry pi and arduino is using serial protocol. I have used this all the time.
There's a module in python for serial communication pyserial.
https://www.electronicwings.com/raspberry-pi/raspberry-pi-uart-communication-using-python-and-c
On my NodeMCU V3 I get a string, convert it to two longs, one int and two bytes, save them in a union and send the whole union to an Arduino Mega, which is supposed to read it in an equal union.
When the NodeMCU prints the bytes to the serial monitor of my laptop it shows their exact value, but after sending them I just get two 0s. Still I think it has something to do with the conversion of the bytes but can't figure out what.
I tried:
Using atol instead of strtol for converting the string, but discarded that
after reading about the
disadvantages. atol() v/s. strtol()
It didn't work anyway.
I tried to convert the bytes with lowByte((int) int1).
Here is the relevant part of my code. I made up a string, instead of receiving one for test purposes.
#include <ESP8266WiFi.h>
union Serial { //Union to place the numbers in.
byte by[12];
struct {
long vsollneu;
long ssollneu;
int phisollneu;
byte priosollneu;
byte typsollneu;
} Befehlssammlung;
} Befehle;
long a1,pr1,ty1;
char str[]="2049714 -1927461000 17 80 4"; //String to be seperated
void convert(char*);
void setup(){
Serial.begin(9600);
}
void loop(){
convert(str);
//Serial.write(Befehle.by,12); //Send the Bytes of the Union to the Arduino MEGA
delay(5555);
}
void convert(char* str){ //Converting the String with strtol
char* ende;
Befehle.Befehlssammlung.vsollneu =strtol(str,&ende,10);
Befehle.Befehlssammlung.ssollneu =strtol(ende,&ende,10);
a1 = strtol(ende,&ende,10);
pr1= strtol(ende,&ende,10);
ty1= strtol(ende,NULL,10);
Befehle.Befehlssammlung.phisollneu=(int) a1; //Converting the long to an int
Befehle.Befehlssammlung.priosollneu=(byte) pr1; //Probably that's somehow wrong???
Befehle.Befehlssammlung.typsollneu=(byte) ty1;
// Serial.println(Befehle.Befehlssammlung.vsollneu);
// Serial.println(Befehle.Befehlssammlung.ssollneu);
// Serial.println(Befehle.Befehlssammlung.phisollneu);
// Serial.println(Befehle.Befehlssammlung.priosollneu);
// Serial.println(Befehle.Befehlssammlung.typsollneu);
}
Here is the receiving part of the Arduino Mega:
union IZweiCkontainer {
byte by[12];
struct {
long vsollneu;
long ssollneu ;
int phisollneu;
byte priosollneu;
byte typsollneu;
} Befehlssammlung;
} Befehle;
void setup(){
Serial.begin(115200); //Serial for debugging
Serial3.begin(9600); //Serial for conncetion the the Mcu
}
void loop(){
if(Serial3.available()>0){
while(Serial3.available()){
Serial3.readBytes(Befehle.by,12); //receiving the Bytes and writing them in the "same" union
}
}
Serial.println(Befehle.Befehlssammlung.vsollneu);
Serial.println(Befehle.Befehlssammlung.ssollneu);
Serial.println(Befehle.Befehlssammlung.phisollneu);
Serial.println(Befehle.Befehlssammlung.priosollneu);
Serial.println(Befehle.Befehlssammlung.typsollneu);
}
What bucks me is that everything is fine on the NodeMCU but after sending I get the following output from the Arduino Mega:
2049714
-1927461000
17
0
0
ints and longs on an Arduino and ESP8266 are not the same size.
Use int16_t and int32_t to make sure they are the same size across different architectures.
union {
byte by[12];
struct {
int32_t vsollneu;
int32_t ssollneu;
int16_t phisollneu;
byte priosollneu;
byte typsollneu;
} Befehlssammlung;
} Befehle;
I'm trying to use the MSPF5529 with my mac. I've downloaded code composer studio and can easily access the chip as well as blink lights and any other application I need.
The goal is for me to print a message using UART through serial communication on my Mac. I am currently using an application called "goSerial" in order to communicate with the chip. My code below initializes UART, takes in a single character, and then it is supposed to print out a character, and then blink a light. However, instead, the code takes in the character, and prints out a strange symbol, called a spacing cedilla, with a hex value of 0xFC, and then blinks the light.
This symbol appears regardless of which character I put into the MSP430 buffer.
My code is listed below. Has anyone had this problem before? How do I solve this?
void Init_UART(void);
void OUTA_UART(unsigned char A);
unsigned char INCHAR_UART(void);
#include "msp430f5529.h"
#include "stdio.h"
int main(void){
volatile unsigned char a;
volatile unsigned int i;
WDTCTL = WDTPW + WDTHOLD;
Init_UART();
a=INCHAR_UART();
a=INCHAR_UART();
OUTA_UART(a);
// go blink the light to indicate code is running
P1DIR |= 0x01;
for (;;){
P1OUT ^= 0x01; i = 10000;
do i--;
while (i != 0); }
}
void OUTA_UART(unsigned char A){
while ((UCA1STAT&UCBUSY));
// send the data to the transmit buffer
UCA1TXBUF =A;
}
unsigned char INCHAR_UART(void){
while ((UCA1STAT&UCBUSY) == 0);
// go get the char from the receive buffer
return (UCA1RXBUF);
}
void Init_UART(void){
P4SEL |= 0x30; // Port 4.4 and port 4.5 controls the transfer
UCA1CTL1|= UCSWRST; // Put state machine in reset
UCA1CTL1|= UCSSEL_1; //Choose 32765Hz
UCA0BR0=3; // Baud rate = 9600
UCA0BR1=0; // Choose 32765 hz
UCA1MCTL=0x06; // Modulation UCBRSx=3, UCBFx = 0
UCA1CTL1 &= ~UCSWRST; // Put USCI in operation mode
}
The UCBUSY flag is not very useful, and cannot be used like this.
That a byte has been received is indicated by UCRXIFG:
while (!(UCA1IFG & UCRXIFG)) ;
return UCA1RXBUF;
That a byte can be sent is indicated by UCTXIFG:
while (!(UCA1IFG & UCTXIFG)) ;
UCA1TXBUF = a;