Without web access, everything is fine.
However, on the exact timing of web request, bytes read on that timing is changed.
My current code just simply shows template webpage and prints IMU accelerometer value only if its magnitude is greater than 2.5. So, if I do not touch MPU9250 sensor, its value should be between 0.9~1.1. However, it prints some wrong values greater than 2.5 when the webpage is refreshed (currently auto-refreshing in 0.5 seconds ) although MPU9250 sensor is not touched at all.
My assumptions are,
1. strong RF signal affects SPI bus so signals are altered.
2. wifi TX routine is called during MPU9250 FIFO readout process and it causes data drop during FIFO read.
I'm using LOLIN D32 PRO board. and MPU9250 is connected its default VSPI bus.
Any possible solution would be appreciated.
MAIN CODE :
- extern volatile int cnt;
- volatile short* buffer;
- volatile short* buffer2;
- volatile unsigned long *timestamp;
- portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
- void printHex( int num, int precision) {
- char tmp[16];
- char format[128];
- sprintf(format, "%%.%dX ", precision);
- sprintf(tmp, format, num);
- if ( strlen( tmp ) > precision + 1 ) {
- int l = strlen( tmp ) - precision - 1;
- for ( int i = 0; i < precision + 2; i++ ) {
- tmp[ i ] = tmp[ i + l ];
- }
- }
- Serial.print(tmp);
- }
- void setup() {
- Serial.begin( 2000000 );
- Serial.println( "Turning on...." );
- buffer = ( short * )ps_malloc( 1000000 );
- buffer2 = ( short * )ps_malloc( 1000000 );
- BUTTONSetup();
- MPU9250Setup();
- OTASetup();
- WEBSERVERSetup();
- Serial.println( "Setup finished." );
- }
- void loop() {
- OTAHandle();
- WEBSERVERHandle();
- int readBytes = 0, readBytes_all = 0;
- while( readBytes = spiread_fifo( buffer + readBytes_all / 2 ) )
- readBytes_all += readBytes;
- if ( readBytes_all == 0 )
- return;
- if( digitalRead( 4 ) == 1 ){
- int x = buffer[ 0 ];
- int y = buffer[ 1 ];
- int z = buffer[ 2 ];
- double m = sqrt( x * x + y * y + z * z ) / 2048;
- if( m > 2.5 )
- Serial.println( m );
- BUTTONHandle();
- }
- }
- #include <SPI.h>
- #define SCK 18
- #define MISO 19
- #define MOSI 23
- #define SS 5
- #define INT 34
- SPIClass MPU9250( VSPI );
- SPISettings settingsA( 1000000, MSBFIRST, SPI_MODE3 );
- SPISettings settingsB( 20000000, MSBFIRST, SPI_MODE3 );
- volatile int cnt = 0;
- void IRAM_ATTR onInterrupt() {
- portENTER_CRITICAL_ISR(&mux);
- cnt++;
- portEXIT_CRITICAL_ISR(&mux);
- }
- void spiwrite( byte a, byte b ) {
- MPU9250.beginTransaction( settingsA );
- digitalWrite( SS, LOW );
- MPU9250.transfer( a );
- MPU9250.transfer( b );
- digitalWrite( SS, HIGH );
- MPU9250.endTransaction();
- }
- byte spiread( byte a ) {
- MPU9250.beginTransaction( settingsB );
- digitalWrite( SS, LOW );
- MPU9250.transfer( a | 0x80 );
- byte r = MPU9250.transfer( 0x00 );
- digitalWrite( SS, HIGH );
- MPU9250.endTransaction();
- return r;
- }
- int spiread_fifo( volatile short * buffer ) {
- int fifo_len = spiread( 0x72 ) * 256 + spiread( 0x73 );
- // fifo_len += 12;
- // fifo_len = fifo_len / 12 * 12;
- if ( fifo_len > 512 )
- return -1;
- if ( fifo_len == 0 )
- return 0;
- MPU9250.beginTransaction( settingsB );
- digitalWrite( SS, LOW );
- MPU9250.transfer( 0x74 | 0x80 );
- MPU9250.transfer( 0x00 ); // if I use SPI CLOCK more than 8~12Mhz, it gives me duplicated byte at the beginning. So just drop one of them.
- for ( int i = 0; i < 3; i++ )
- buffer[ i ] = MPU9250.transfer16( 0x00 );
- for ( int i = 3; i < fifo_len / 2; i++ )
- MPU9250.transfer16( 0x00 );
- // for( int i = fifo_len / 2 + 1; i < fifo_len; i++ )
- // buffer[ i ] = 0;
- digitalWrite( SS, HIGH );
- MPU9250.endTransaction();
- for ( int i = 0; i < 12; i++ )
- __asm__ __volatile__ ("nop\n\t");
- return fifo_len;
- }
- void spiread_raw( volatile short * buffer ) {
- MPU9250.beginTransaction( settingsB );
- digitalWrite( SS, LOW );
- MPU9250.transfer( 0x3b | 0x80 );
- for ( int i = 0; i < 3; i++ )
- buffer[ i ] = MPU9250.transfer16( 0x00 );
- digitalWrite( SS, HIGH );
- MPU9250.endTransaction();
- for ( int i = 0; i < 12; i++ )
- __asm__ __volatile__ ("nop\n\t");
- }
- void spiread_raw_gyr( volatile short * buffer ) {
- MPU9250.beginTransaction( settingsB );
- digitalWrite( SS, LOW );
- MPU9250.transfer( 0x43 | 0x80 );
- for ( int i = 0; i < 3; i++ )
- buffer[ i ] = MPU9250.transfer16( 0x00 );
- digitalWrite( SS, HIGH );
- MPU9250.endTransaction();
- for ( int i = 0; i < 12; i++ )
- __asm__ __volatile__ ("nop\n\t");
- }
- void spiread_raw_accgyr( volatile short * buffer ) {
- MPU9250.beginTransaction( settingsB );
- digitalWrite( SS, LOW );
- MPU9250.transfer( 0x3b | 0x80 );
- for ( int i = 0; i < 3; i++ )
- buffer[ i ] = MPU9250.transfer16( 0x00 );
- MPU9250.transfer16( 0x00 );
- for ( int i = 3; i < 6; i++ )
- buffer[ i ] = MPU9250.transfer16( 0x00 );
- digitalWrite( SS, HIGH );
- MPU9250.endTransaction();
- for ( int i = 0; i < 12; i++ )
- __asm__ __volatile__ ("nop\n\t");
- }
- void MPU9250Setup(){
- pinMode( SS, OUTPUT );
- pinMode( SCK, OUTPUT );
- pinMode( MOSI, OUTPUT );
- pinMode( INT, INPUT_PULLUP );
- pinMode( MISO, INPUT );
- pinMode( 4, INPUT );
- MPU9250.begin( SCK, MISO, MOSI, SS ); //CLK,MISO,MOIS,SS
- attachInterrupt( digitalPinToInterrupt( INT ), onInterrupt, FALLING );
- spiwrite( 0x68, 0x07 );
- spiwrite( 0x6A, 0x55 ); // FIFO_EN = 1, FIFO_RST = 1;
- spiwrite( 0x19, 0x00 ); // SMPLRT_DIV = 0
- spiwrite( 0x1B, 0x18 ); // GYRO_FS_SEL = 3, Fchoice_b = 0
- spiwrite( 0x1C, 0x18 ); // ACCEL_FS_SEL = 3
- spiwrite( 0x1D, 0x08 ); // accel_fchoice_b = 1
- // spiwrite( 0x23, 0x78 ); // TEMP_OUT = 0, GYRO_XOUT = 1, GYRO_YOUT = 1, GYRO_ZOUT = 1, ACCEL = 1
- // spiwrite( 0x23, 0x79 ); // TEMP_OUT = 0, GYRO_XOUT = 0, GYRO_YOUT = 0, GYRO_ZOUT = 0, ACCEL = 1
- spiwrite( 0x23, 0x08 ); // TEMP_OUT = 0, GYRO_XOUT = 0, GYRO_YOUT = 0, GYRO_ZOUT = 0, ACCEL = 1
- spiwrite( 0x37, 0x10 ); // INT_ANYRD_2CLEAR = 1
- spiwrite( 0x38, 0xC1 ); // ACTL = 1, OPEN = 1, RAW_RDY_EN = 1
- spiwrite( 0x1A, 0x07 ); // FIFO_MODE = 0, EXT_SYNC_SET = 0, DLPF_CFG = 7
- }
- #include <WiFi.h>
- #include "esp_wifi.h"
- #include <ESPmDNS.h>
- #include <WiFiUdp.h>
- #include <ArduinoOTA.h>
- const char* ssid = "XXXX";
- const char* password = "XXXX";
- void OTASetup(){
- delay( 100 );
- esp_wifi_set_max_tx_power( -100 );
- WiFi.mode( WIFI_STA );
- WiFi.setHostname( "LOLIN_D32_PRO_Sunkyue" );
- delay( 100 );
- WiFi.begin( ssid, password );
- while( WiFi.waitForConnectResult() != WL_CONNECTED ){
- Serial.println( "Connection Failed! Rebooting..." );
- delay( 10 );
- ESP.restart();
- }
- ArduinoOTA.setPort(53232);
- ArduinoOTA.setHostname("LOLIN_D32_PRO_Sunkyue");
- ArduinoOTA.setPassword("XXXX");
- ArduinoOTA
- .onStart([]() {
- String type;
- if (ArduinoOTA.getCommand() == U_FLASH)
- type = "sketch";
- else // U_SPIFFS
- type = "filesystem";
- // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
- Serial.println("Start updating " + type);
- })
- .onEnd([]() {
- Serial.println("\nEnd");
- })
- .onProgress([](unsigned int progress, unsigned int total) {
- Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
- })
- .onError([](ota_error_t error) {
- Serial.printf("Error[%u]: ", error);
- if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
- else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
- else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
- else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
- else if (error == OTA_END_ERROR) Serial.println("End Failed");
- });
- ArduinoOTA.begin();
- Serial.println("Ready");
- Serial.print("IP address: ");
- Serial.println(WiFi.localIP());
- }
- void OTAHandle(){
- ArduinoOTA.handle();
- }
- #include <WiFiClient.h>
- #include <WebServer.h>
- WebServer server(80);
- void handleRoot() {
- char temp[400];
- int sec = millis() / 1000;
- int min = sec / 60;
- int hr = min / 60;
- snprintf(temp, 400,
- "<html>\
- <head>\
- <meta http-equiv='refresh' content='0.5'/>\
- <title>ESP32 Demo</title>\
- <style>\
- body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\
- </style>\
- </head>\
- <body>\
- <h1>Hello from ESP32!</h1>\
- <p>Uptime: %02d:%02d:%02d</p>\
- <img src=\"/test.svg\" />\
- </body>\
- </html>",
- hr, min % 60, sec % 60
- );
- server.send(200, "text/html", temp);
- }
- void handleNotFound() {
- String message = "File Not Found\n\n";
- message += "URI: ";
- message += server.uri();
- message += "\nMethod: ";
- message += (server.method() == HTTP_GET) ? "GET" : "POST";
- message += "\nArguments: ";
- message += server.args();
- message += "\n";
- for (uint8_t i = 0; i < server.args(); i++) {
- message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
- }
- server.send(404, "text/plain", message);
- }
- void drawGraph() {
- String out = "";
- char temp[100];
- out += "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"400\" height=\"150\">\n";
- out += "<rect width=\"400\" height=\"150\" fill=\"rgb(250, 230, 210)\" stroke-width=\"1\" stroke=\"rgb(0, 0, 0)\" />\n";
- out += "<g stroke=\"black\">\n";
- int y = rand() % 130;
- for (int x = 10; x < 390; x += 10) {
- int y2 = rand() % 130;
- sprintf(temp, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke-width=\"1\" />\n", x, 140 - y, x + 10, 140 - y2);
- out += temp;
- y = y2;
- }
- out += "</g>\n</svg>\n";
- server.send(200, "image/svg+xml", out);
- }
- void WEBSERVERSetup(){
- if (MDNS.begin("esp32")) {
- Serial.println("MDNS responder started");
- }
- server.on("/", handleRoot);
- server.on("/test.svg", drawGraph);
- server.on("/inline", []() {
- server.send(200, "text/plain", "this works as well");
- });
- server.onNotFound(handleNotFound);
- server.begin();
- }
- void WEBSERVERHandle(){
- server.handleClient();
- }