I have a problem with my esp8266 project. My purpose is to use esp8266 to transmit beacon frames every one second so that my android device or my laptop can receive it and display in list of APs which i can connect to.
Here is my code I wrote:
#include <ESP8266WiFi.h>
extern "C" {
#include "user_interface.h"
}
void setup() {
delay(500);
sendBeacon("ESP8266");
ESP.deepSleep(10e5);
}
void loop() {
}
void sendBeacon(char* ssid) {
// Randomize channel //
byte channel = 1;
wifi_set_channel(channel);
uint8_t packet[128] = { 0x80, 0x00, //Frame Control
0x00, 0x00, //Duration
/*4*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //Destination address
/*10*/ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, //Source address - overwritten later
/*16*/ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, //BSSID - overwritten to the same as the source address
/*22*/ 0xc0, 0x6c, //Seq-ctl
//Frame body starts here
/*24*/ 0x83, 0x51, 0xf7, 0x8f, 0x0f, 0x00, 0x00, 0x00, //timestamp - the number of microseconds the AP has been active
/*32*/ 0xFF, 0x00, //Beacon interval
/*34*/ 0x01, 0x04, //Capability info
/* SSID */
/*36*/ 0x00
};
int ssidLen = strlen(ssid);
packet[37] = ssidLen;
for(int i = 0; i < ssidLen; i++) {
packet[38+i] = ssid[i];
}
uint8_t postSSID[13] = {0x01, 0x08, 0x82, 0x84, 0x8b, 0x96, 0x24, 0x30, 0x48, 0x6c, //supported rate
0x03, 0x01, 0x04 /*DSSS (Current Channel)*/ };
for(int i = 0; i < 12; i++) {
packet[38 + ssidLen + i] = postSSID[i];
}
packet[50 + ssidLen] = channel;
// get SRC MAC
unsigned char mac[6];
WiFi.macAddress(mac);
packet[10] = packet[16] = mac[0];
packet[11] = packet[17] = mac[1];
packet[12] = packet[18] = mac[2];
packet[13] = packet[19] = mac[3];
packet[14] = packet[20] = mac[4];
packet[15] = packet[21] = mac[5];
int packetSize = 51 + ssidLen;
wifi_send_pkt_freedom(packet, packetSize, 0);
delay(1);
}
I used tcpdump to capture those frame and yes, they are there. But I still couldn't see it in list of AP on my laptop and my android device.
I can see it if I stop using deep sleep mode. For example:
#include <ESP8266WiFi.h>
extern "C" {
#include "user_interface.h"
}
void setup() {
delay(500);
// sendBeacon("ESP8266");
// ESP.deepSleep(10e5);
}
void loop() {
sendBeacon("ESP8266");
}
void sendBeacon(char* ssid) {
// Randomize channel //
byte channel = 1;
wifi_set_channel(channel);
uint8_t packet[128] = { 0x80, 0x00, //Frame Control
0x00, 0x00, //Duration
/*4*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //Destination address
/*10*/ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, //Source address - overwritten later
/*16*/ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, //BSSID - overwritten to the same as the source address
/*22*/ 0xc0, 0x6c, //Seq-ctl
//Frame body starts here
/*24*/ 0x83, 0x51, 0xf7, 0x8f, 0x0f, 0x00, 0x00, 0x00, //timestamp - the number of microseconds the AP has been active
/*32*/ 0xFF, 0x00, //Beacon interval
/*34*/ 0x01, 0x04, //Capability info
/* SSID */
/*36*/ 0x00
};
int ssidLen = strlen(ssid);
packet[37] = ssidLen;
for(int i = 0; i < ssidLen; i++) {
packet[38+i] = ssid[i];
}
uint8_t postSSID[13] = {0x01, 0x08, 0x82, 0x84, 0x8b, 0x96, 0x24, 0x30, 0x48, 0x6c, //supported rate
0x03, 0x01, 0x04 /*DSSS (Current Channel)*/ };
for(int i = 0; i < 12; i++) {
packet[38 + ssidLen + i] = postSSID[i];
}
packet[50 + ssidLen] = channel;
// get SRC MAC
unsigned char mac[6];
WiFi.macAddress(mac);
packet[10] = packet[16] = mac[0];
packet[11] = packet[17] = mac[1];
packet[12] = packet[18] = mac[2];
packet[13] = packet[19] = mac[3];
packet[14] = packet[20] = mac[4];
packet[15] = packet[21] = mac[5];
int packetSize = 51 + ssidLen;
wifi_send_pkt_freedom(packet, packetSize, 0);
delay(1);
}
Does anyone know why? Please help me to get this, thanks!
First of all, ESP.deepSleep(10e5) makes the processor sleep for 100ms, not a second. The correct would be ESP.deepSleep(10e6). Secondly, you are trying to send just one packet every second or so, it's quite hard to make sure that the wifi reading from the device is gonna get that packet for sure and display it on the list of SSIDs. From my experiments, I had to send three packets every 200ms to make sure it was displayed on my android mobile and pc. You can try to play with the number of packets you send and the interval to see what fits you best...
Also, make sure to configure the ESP correctly at the setup function. When I tried my similar code I had to use two instructions: wifi_set_opmode(STATION_MODE) and wifi_promiscuous_enable(1)
Is it possible to add an binary data file together with a Arduino sketch that is transferred when sending it over to the Arduino? I manage to add the file in the IDE and it was copied to a "data" directory in my project folder but I can't find a way to access it in my code.
I'm just interested to send one file for testing purposes and don't want to use SD cards or network. I'm using the Arduino-Uno.
You can convert the binary data to a C array, and insert that into the code/source which will allow you to reference it.
A tool like Hexworkshop or other binary file editor should have an option to do this for you.
You could check this answer as well.
Example output:
unsigned char data[84] = {
0x02, 0x00, 0x41, 0x8E, 0x08, 0x8F, 0x09, 0x85, 0x09, 0x82, 0x85, 0x08, 0x83, 0xE0, 0xFE, 0xA3,
0xE0, 0x8E, 0x0A, 0xF5, 0x0B, 0x4E, 0x70, 0xEF, 0x85, 0x09, 0x82, 0x85, 0x08, 0x83, 0xE0, 0xFE,
0xA3, 0xE0, 0xFF, 0x7C, 0x00, 0x7D, 0x00, 0x02, 0x00, 0x00, 0x7B, 0x00, 0x7A, 0x00, 0x79, 0x01,
0x80, 0x06, 0x7B, 0x00, 0x7A, 0x00, 0x79, 0x00, 0x8A, 0x0A, 0x89, 0x0B, 0xE9, 0x4A, 0x70, 0xD8,
0x22, 0x78, 0x7F, 0xE4, 0xF6, 0xD8, 0xFD, 0x75, 0x81, 0x0B, 0x02, 0x00, 0x4D, 0x7F, 0x00, 0x7E,
0x80, 0x02, 0x00, 0x03,
} ;
I'm making an application, using raw sockets and need your advice:
The application is a tester of some kind of tcp/ip stack.
What I need I have an application that connects with a remote server and transmits some data to id.
lets say - I cannot open sockets from my application - all I have is tcp/Ip buffer with all headers and so on.
For testing I wanna make 2 raw sockets - 1 for sending and 1 for receiving ip buffers.
for receiving i have this code:
int saddr_size , data_size;
struct sockaddr saddr;
unsigned char *buffer = (unsigned char *)malloc(65536); //Its Big!
printf("Starting...\n");
//Create a raw socket that shall sniff
sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
if(sock_raw < 0)
{
printf("Socket Error\n");
return 1;
}
while(1)
{
saddr_size = sizeof saddr;
//Receive a packet
data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , &saddr_size);
if(data_size <0 )
{
printf("Recvfrom error , failed to get packets\n");
return 1;
}
printf("Data size = %d", data_size);
}
close(sock_raw);
printf("Finished");
return 0;
And as I can see it works - it gets all TCP/IP packets.
For sender I tryed this
static const unsigned char pkt6[60] = {
0x32, 0x04, 0x34, 0xed, 0xf3, 0xab, 0x01, 0x02, /* 2.4..... */
0x03, 0x04, 0x05, 0x06, 0x08, 0x00, 0x45, 0x00, /* ......E. */
0x00, 0x2e, 0x00, 0x02, 0x00, 0x00, 0xff, 0x06, /* ........ */
0x44, 0xc5, 0xc0, 0xa8, 0x01, 0x02, 0xac, 0x11, /* D....... */
0x09, 0x47, 0x00, 0x08, 0x1a, 0x0b, 0x00, 0x00, /* .G...... */
0x19, 0x6e, 0x23, 0x17, 0xc8, 0x36, 0x50, 0x18, /* .n#..6P. */
0x08, 0x60, 0x2b, 0xb9, 0x00, 0x00, 0x6c, 0x6f, /* .`+...lo */
0x6f, 0x6c, 0x0a, 0x00 /* ol.. */
};
if((s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {
perror("error:");
exit(EXIT_FAILURE);
}
while(1) {
if(send(s, pkt6, sizeof(pkt6), 0)< 0)
perror("error::");
}
}
And it always says
error:: Destination address required
So what do I need to change if i want to send READy IP packets and get raw ip packets?
I've not use raw sockets this way myself, but AIUI you'll probably need to use sendto() instead of send(), and pass the saddr structure that you obtained in the recvfrom() call.
UPDATE: I can't even get this calculator to reproduce the SMBus PECs illustrated in figures 8 and 9 of this datasheet!
So I'm interfacing an arduino with a Melexis temperature sensor, and it's going okay--aside from the fact that I can't seem to get the CRC check to work.
I've gotten read operations to complete successfully (although my software ignores the packet error code) but I have tried a lot of implementations of CRC8 to check the PEC byte to no avail. The code block I am using now came from OneWire:
uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len)
{
uint8_t crc = 0;
while (len--) {
uint8_t inbyte = *addr++;
for (uint8_t i = 8; i; i--) {
uint8_t mix = (crc ^ inbyte) & 0x01;
crc >>= 1;
if (mix) crc ^= 0x8C;
inbyte >>= 1;
}
}
return crc;
}
I rewrote it to consider just the one byte:
int smbCRC(int message) {
uint8_t crc = 0;
uint8_t inbyte = message & 0xFF;
for (uint8_t i = 8; i; i--) {
uint8_t mix = (crc ^ inbyte) & 0x01;
crc >>= 1;
if (mix) crc ^= 0x8C;
inbyte >>= 1;
}
return crc;
}
But its CRC does not match that of the MLX datasheet (Figure 8 from here for example). When I print an int with its CRC8 like so:
int message = 0x3aD2;
lcd.print(String(message,HEX) + " " + String(smbCRC(message),HEX));
I get back "3ad2 eb", though the datasheet says the correct PEC is 0x30. Where am I going wrong? It seems like this could be caused by a bad implementation of CRC or bad assumptions on my part about the CRC input, and I'm not sure where to start troubleshooting.
I haven't checked your CRC implementation but there is a mistake in the MLX datasheet or at least it's badly written. You have to include all the I2C frame's data for the PEC's calculation not just the replied data.
For a read word command you have to include [SA_W, Command, SA_R, LSB, MSB] and for a write word command [SA_W, Command, LSB, MSB].
So, for their first example the calculation must be made on [ 0xB4, 0x07, 0xB5, 0xD2, 0x3A ] and not just on [ 0xD2, 0x3A ] and this way you get the expected 0x30.
Here is a simple C implementation of the CRC with a lookup table (non Arduino but it must be quite simple to adapt):
static const uint8_t crc_table[] = {
0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31,
0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9,
0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1,
0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe,
0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16,
0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 0x89, 0x8e, 0x87, 0x80,
0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8,
0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10,
0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f,
0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7,
0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef,
0xfa, 0xfd, 0xf4, 0xf3
};
uint8_t
crc8(uint8_t *p, uint8_t len)
{
uint16_t i;
uint16_t crc = 0x0;
while (len--) {
i = (crc ^ *p++) & 0xFF;
crc = (crc_table[i] ^ (crc << 8)) & 0xFF;
}
return crc & 0xFF;
}
It is possible to get the compiler to figure out the lookup table for you, as follows:
#include <stdio.h>
#include <stdint.h>
/* * *
* Just change this define to whatever polynomial is in use
*/
#define CRC1B(b) ( (uint8_t)((b)<<1) ^ ((b)&0x80? 0x07 : 0) ) // MS first
/* * *
* 8+1 entry enum lookup table define
*/
#define CRC(b) CRC_##b // or CRC8B(b)
enum {
CRC(0x01) = CRC1B(0x80),
CRC(0x02) = CRC1B(CRC(0x01)),
CRC(0x04) = CRC1B(CRC(0x02)),
CRC(0x08) = CRC1B(CRC(0x04)),
CRC(0x10) = CRC1B(CRC(0x08)),
CRC(0x20) = CRC1B(CRC(0x10)),
CRC(0x40) = CRC1B(CRC(0x20)),
CRC(0x80) = CRC1B(CRC(0x40)),
// Add 0x03 to optimise in CRCTAB1
CRC(0x03) = CRC(0x02)^CRC(0x01)
};
/* * *
* Build a 256 byte CRC constant lookup table, built from from a reduced constant
* lookup table, namely CRC of each bit, 0x00 to 0x80. These will be defined as
* enumerations to take it easy on the compiler. This depends on the relation:
* CRC(a^b) = CRC(a)^CRC(b)
* In other words, we can build up each byte CRC as the xor of the CRC of each bit.
* So CRC(0x05) = CRC(0x04)^CRC(0x01). We include the CRC of 0x03 for a little more
* optimisation, since CRCTAB1 can use it instead of CRC(0x01)^CRC(0x02), again a
* little easier on the compiler.
*/
#define CRCTAB1(ex) CRC(0x01)ex, CRC(0x02)ex, CRC(0x03)ex,
#define CRCTAB2(ex) CRCTAB1(ex) CRC(0x04)ex, CRCTAB1(^CRC(0x04)ex)
#define CRCTAB3(ex) CRCTAB2(ex) CRC(0x08)ex, CRCTAB2(^CRC(0x08)ex)
#define CRCTAB4(ex) CRCTAB3(ex) CRC(0x10)ex, CRCTAB3(^CRC(0x10)ex)
#define CRCTAB5(ex) CRCTAB4(ex) CRC(0x20)ex, CRCTAB4(^CRC(0x20)ex)
#define CRCTAB6(ex) CRCTAB5(ex) CRC(0x40)ex, CRCTAB5(^CRC(0x40)ex)
/* * *
* This is the final lookup table. It is rough on the compiler, but generates the
* required lookup table automagically at compile time.
*/
static const uint8_t crc_table[256] = { 0, CRCTAB6() CRC(0x80), CRCTAB6(^CRC(0x80)) };
uint8_t crc8(uint8_t *p, uint8_t len)
{
uint8_t crc = 0x0;
while (len--) {
crc = crc_table[crc ^ *p++];
}
return crc;
}
void main( void )
{
int i, j;
printf("static const uint8_t crc_table[] = {");
for (i = 0; i < 0x10; i++)
{
printf("\n ");
for (j = 0; j < 0x10; j++)
{
printf( " 0x%02x,", crc_table[i*0x10+j] );
}
}
printf("\n};\n\n");
}
See reference on following links:
http://www.melexis.com/Asset/SMBus-communication-with-MLX90614-DownloadLink-5207.aspx
http://www.sbs-forum.org/marcom/dc2/20_crc-8_firmware_implementations.pdf
Function code for Arduino:
byte c8( byte x ){
for( byte i = 8; i--; ) {
x = ( x << 1 ) ^ ( x & 128 ? 7 : 0 );
}
return x;
}
void setup() {
Serial.begin( 9600 );
int msg = 0x3AD2;
Serial.print( '0x' );
Serial.print( c8( msg ), HEX );
// '0x30' is displayed on Serial Monitor
}
void loop() {}
Since argument x is strong-typed as byte (uint8_t), word-size data (such 0x3AD2) will be truncated to byte-size (which is 0xD2 in case of 0x3AD2).
Stripped code from linux kernel code, i am using it for smbus pec calculation..
#include<stdio.h>
#define POLY (0x1070U << 3)
#define DST_SLAVE_ADDRESS 0x1d //7-bit Slave Address
static unsigned char crc8(short int data)
{
int i;
for (i = 0; i < 8; i++) {
if (data & 0x8000)
data = data ^ POLY;
data = data << 1;
}
return (unsigned char)(data >> 8);
}
unsigned char i2c_smbus_pec(unsigned char crc, unsigned char *p, int count)
{
int i;
for (i = 0; i < count; i++)
crc = crc8((crc ^ p[i]) << 8);
return crc;
}
/* Assume a 7-bit address, which is reasonable for SMBus */
static unsigned char i2c_smbus_msg_pec(unsigned char slave_addr, char *msg, int len)
{
/* The address will be sent first */
unsigned char addr = slave_addr << 1;
int pec;
pec = i2c_smbus_pec(0, &addr, 1);
/* The data buffer follows */
return i2c_smbus_pec(pec, msg, len);
}
main()
{
//SMBUS PEC include everthing include dst slave address
//dst i2c address here is 0x1d (7bit) , 0x3a (8bit)
char msg[] = {0x0F,0x19,0x21,0x01,0x00,0x00,0xEB,0x84,0x08,0x00,0x00,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xAA,0xEF,0x81,0xB4};
//dst i2c address here is 0x10 (7bit) , 0x20 (8bit)
//char msg[] = { 0x0F,0x19,0x3B,0x01,0x00,0x00,0xD3,0x84,0x88,0x00,0x00,0x00,
// 0x00,0x00,0x00,0x30,0xFF,0xEF,0x00,0x00,0x00,0x00,0x00,0x21,0xE5,0xD5,0xA8};
int len = sizeof(msg);
int calc_pec = i2c_smbus_msg_pec(DST_SLAVE_ADDRESS, msg , len);
printf("pec = 0x%x\n", calc_pec);
}