Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DMA ADC Fails On Connection to AP when in STA (station) mode (IDFGH-239) (IDFGH-1442) #3714

Closed
mishafarms opened this issue Jun 30, 2019 · 30 comments

Comments

@mishafarms
Copy link

This is a duplicate of #1977. It appears that has been open for over a year.

Development Kit: Platform IO
Kit version (for WroverKit/PicoKit/DevKitC): v3.1-dev-661-gf586f5e6
Core (if using chip or module): ESP32 Lolin
IDF version v3.1-dev-661-gf586f5e6
Development Env: VS Code + PlatformIO
Operating System: Windows
Power Supply: USB

Platform Espressif 32 (Stage)

Updating espressif32 @ 29b3a81
Updating tool-esptoolpy @ 1.20100.0
Updating framework-arduinoespressif32 @ 6826508
Updating tool-espotapy @ 1.1.0
Problem Description

When acquiring ADC data through DMA transfers and the device is in station mode (WIFI_MODE_STA). As the device connects to the AP, the ADC DMA buffer ceases to show valid data and continues to read (a probably random) fixed value.

This does not happen in WIFI_MODE_AP or WIFI_MODE_APSTA
Expected Behavior

The ADC should continue to read valid data.
Actual Behavior

C00, F06, 3E6, 7E8, 0, 2D, 604, 22F, DFF, A84, F84, FE0, 8D2, CF2, FE, 4E1, 18E, 0, 93A, 518, F94, D2C, 9F0, FF0, 21F, 5CA, 66, 0, 84C, 430, F38, C62, E7C, FF0, 6C3,
B00, 0, 300, 34E, 0, B80, 748, FFC, EB0, C00, F00, 3AF, 7A6, 0, E, 670, 27E, E12, A8F, F80, FE0, 8DC, CB1, D5, 49E, 168, 0, 964, 580,
0, 9D, 5C0, 20C, DC0, 9FF, FC7, FCF, 900, D27, 160, 500, 11C, 0, 900, 4CE, F8D, D0F, DE2, FD4, 5E9, A45, 0, 218, 3EF, 3F, C38, 7FF, FFD, F1E, B03, EA7, 300, 71A, 0, 0, 700, 302, E8E, B48, F00, FFE, 7E6, C12, 33, 3FE, 22B, 0, A6E, 60F, FE0, DE0, CFF, F86, 4D8, 90A, 0, 104, 509, 14E, D22, 931, FA4, F92,
160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,

Steps to repropduce

Start WiFi.
Start ADC acquisition.
Wait for device to connect to AP.

Code to reproduce this issue

#include <Arduino.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_log.h"
#include "driver/i2s.h"
#include "soc/syscon_reg.h"
#include "driver/adc.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "WiFi.h"
#include "dac_cosine.h"
#define TAG "adc_i2s"

// Physically connect pins 25 and 34

uint32_t SAMPLE_RATE = 120E3;
uint32_t NUM_SAMPLES = 64;
uint32_t SIGNAL_FREQ = 10E3;

#define WIFICLIENT_SSID ("MYAP")
#define WIFICLIENT_PWD ("1234567")

#define WIFISERVER_SSID ("MYDAQ")
#define WIFISERVER_PWD ("1234567")

IPAddress local_IP(192,168,4,22);
IPAddress gateway(192,168,4,22);
IPAddress subnet(255,255,255,0);

static QueueHandle_t i2s_event_queue;
static EventGroupHandle_t wifi_event_group;

void WiFiEvent(WiFiEvent_t event)
{
switch(event) {
case SYSTEM_EVENT_STA_GOT_IP:{
Serial.println();
Serial.println("CONNECTED");
Serial.println();
break;
}
default:{
break;
}
} // switch
} // WiFiEvent

void setup(){
Serial.begin(921600);
WiFi.onEvent(WiFiEvent);
WiFi.mode(WIFI_MODE_STA);
WiFi.begin(WIFICLIENT_SSID, WIFICLIENT_PWD);

i2s_config_t i2s_config ;
i2s_config.mode =  i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN);
i2s_config.sample_rate = SAMPLE_RATE;                           // 120 KHz
i2s_config.dma_buf_len = NUM_SAMPLES;                           // 512
i2s_config.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT;         // Should be mono but doesn't seem to be
i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
i2s_config.use_apll = true,
i2s_config.fixed_mclk = SAMPLE_RATE;
i2s_config.communication_format = I2S_COMM_FORMAT_I2S;
i2s_config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1;
i2s_config.dma_buf_count = 2;
//install and start i2s driver
i2s_driver_install(I2S_NUM_0, &i2s_config, 1, &i2s_event_queue);
// Connect ADC to I2S
i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_6);

// Generate test signal
int step = nearbyint(0.008192 * SIGNAL_FREQ);       // ~10kHz
dac_cosine_enable(DAC_CHANNEL_1);                   // enable the generator
dac_frequency_set(0, step);                         // frequency setting is common to both channels
dac_scale_set(DAC_CHANNEL_1, 0);                    // No scaling (0~3.7v)
dac_offset_set(DAC_CHANNEL_1, 0);                   // No Offest
dac_invert_set(DAC_CHANNEL_1, 2);                   // Sinewave
dac_output_enable(DAC_CHANNEL_1);                   // Start DAC

i2s_adc_enable(I2S_NUM_0);                          // Start ADC

}

void loop(){
uint16_t i2s_read_buff[NUM_SAMPLES];
system_event_t evt;
if (xQueueReceive(i2s_event_queue, &evt, portMAX_DELAY) == pdPASS) {
if (evt.event_id==2) {
i2s_read_bytes(I2S_NUM_0, (char*)i2s_read_buff, NUM_SAMPLES * 2, portMAX_DELAY);
for (int i=0;i<NUM_SAMPLES;i++){
Serial.printf("%X, ", i2s_read_buff[i] & 0xFFF);
}
Serial.println();
}
}
}

@github-actions github-actions bot changed the title DMA ADC Fails On Connection to AP when in STA (station) mode (IDFGH-239) DMA ADC Fails On Connection to AP when in STA (station) mode (IDFGH-239) (IDFGH-1442) Jun 30, 2019
@giPeteR
Copy link

giPeteR commented Jul 1, 2019

I would like to know as well. Spent well over a week trying to get ADC1 working before finding these threads.
ADC1 stops as soon as doing esp_wifi_connect().
It works if I do an esp_wifi_disconnect() before i2s_read().
Feels so odd that the datasheet claims a high performance ADC, but you cannot really use it.
I also like to get the pattern table running because I need several channels at high speed, but haven't got it to work.

@mishafarms
Copy link
Author

mishafarms commented Jul 1, 2019

What did you do to get the pattern table working? I got it to work by removing the static in front of the 2 functions in the file in the esp-idf/components/driver/rtc_module.c and added the declaration into esp-idf/components/driver/include/driver/adc.h

esp_err_t adc_set_i2s_data_len(adc_unit_t adc_unit, int patt_len);
esp_err_t adc_set_i2s_data_pattern(adc_unit_t adc_unit, int seq_num, adc_channel_t channel, adc_bits_width_t bits, adc_atten_t atten);

I then call these functions in my code.
// add second channel
adc_set_i2s_data_pattern(I2S_ADC_UNIT, 1, I2S_ADC_CHANNEL2, ADC_WIDTH_12Bit, ADC_ATTEN_11db);
adc_set_i2s_data_len(I2S_ADC_UNIT, 2);

I then got the data interleaved. You have to double the sample rate for 2 channels.

I think there is some way to copy the driver files into your components directory and not modify the
released version, But I haven't gotten that to work yet.
Michael

@detly
Copy link

detly commented Jul 2, 2019

Re. pattern table usage, you might be interested in the example code I posted from issue #3263 . @mishafarms did you get a problem with weird channel ordering (like 5, 5, 6, 6, 5, 6, 6)?

Re. ADC issues, I notice you're using the APLL, and you might be running into the issue I found here (APLL cannot be used while using the I2S direct-from-ADC mode): #3692 .

Re. the ADC issue itself, I dimly remember that one of the ADC modules is incompatible with the wifi module being enabled, but I'll have to dig that up.

@detly
Copy link

detly commented Jul 2, 2019

Oh, it was ADC2 and you're using ADC1, so it's probably not that. From here:

ADC2 is used by the Wi-Fi driver. Therefore the application can only use ADC2 when the Wi-Fi driver has not started.

@mishafarms
Copy link
Author

I tried disabling APLL, no change.

I did not see any weird channel ordering.

Michael

@detly
Copy link

detly commented Jul 2, 2019

@michafarms I suspect you might not really be using the APLL in your posted code anyway. The fixed_mclk is set to your sample rate, which is far higher than the MCLK value is allowed to be. The code in the RTC module will fall back to the PLL D2, and the only sign of this will be a debug line that looks like:

I (3484) I2S: PLL_D2: Req RATE: 

@detly
Copy link

detly commented Jul 2, 2019

@mishafarms It seems like we're working with similar features. I'm totally unable to get the channel ordering/pattern table working though. If you have a few minutes, do you think you could build and run the project here and see if you get the same bug I do? It would be a huge help just to have another data point for this.

@giPeteR
Copy link

giPeteR commented Jul 7, 2019

ADC1 pattern table! => SOLVED
ADC1 + WiFi => SOLVED (disable WiFi power save, not included in my example)

I finally got the ADC1 pattern tables to work, but not with WiFi connected.
I use DevKitC with ESP32-WROVER-B, 240MHz.
Please see provided code which I tried to add a lot of comments in.
You can choose whether to turn WiFi on/off, or disconnect before starting I2S ADC1 DMA.
It doesn't matter if you initialise I2S before or after Wifi, or if running WiFi on PRO_CPU and I2S on APP_CPU.

Sample rate can be from 5kHz up to 1.3MHz!
ESP32 Datasheet 4.1.2 says max 2Msps (not sure how to get there).
Have not checked if output rate gets divided by number of channels (probably does).

I also tried starting WiFi after i2s_adc_enable(); but before i2s_read(); . It doesn't help.

Sample output from channel 0, 3, 6, 7, looks like this:
I (23161) ADC/DAC: 6a 07 a7 75 67 69 56 3a 67 07 a7 75 6b 69 51 3a
Chan[n] : ADC raw; [0] : 076a, [3] : 0a56, [6] : 0967, [7] : 05a7

The full code...
Copy your ESP_IDF example structure:

examples\peripherals\i2s_adc_dac\main\app_main.c

and replace everything in app_main.c with this:
i2s_adc_dac.zip
Or delete app_main.c and rename this to app_main.c

@mishafarms
Copy link
Author

That is great.

I wish someone would look at the original issue.

Michael

@tony-ward
Copy link

All, I want to jump in here, I have exactly the same. All is running, then as soon as STA connects it stops, keeping the existing value in all entries...

@negativekelvin
Copy link
Contributor

Running @giPeteR example connected to STA I am getting changing ADC raw values. This is on fairly recent master branch.

@koobest
Copy link
Contributor

koobest commented Jul 15, 2019

Hi,
I think this is the same issue as #1333, we fixed it on ESP-IDF(update rtc library on the master), but I'm not sure if this fix has been applied to the arduino project. Another solution to this issue is to initialize the ADC after WIFI initialization and connection.

thanks!!

@tony-ward
Copy link

Guys this is not the same, and I am not running on Arduino. I have tried to initialise the ADC after WIFI and before WIFI and I get the same results.

@mishafarms
Copy link
Author

mishafarms commented Jul 15, 2019

I also am NOT using the Arduino. I am using a single channel. I am on the master branch of esp-idf.
It doesn't seem to matter the order that you initialize.

I think that this is still an issue.
Michael

@negativekelvin
Copy link
Contributor

@mishafarms can you reproduce with the example given by giPeteR above? What settings necessary to reproduce?

@mishafarms
Copy link
Author

@negativekelvin I just ran giPeteR's code and it works. I get all the channels data.
But when I enable the Wifi it fails. It does not even print out all the
channels anymore.

If you put this code in the app_main function.

while(1)
{
	vTaskDelay(10000 / portTICK_PERIOD_MS);
	skip_connect = 0;
	esp_wifi_connect();
}

You get the correct data for about 5 samples and then
when it reconnects to the Wifi it fails. Here is the output from my test.

I (10996) ADC/DAC: 79 07 7e 07 ce 60 98 30 7d 07 7f 70 c0 60 cb 30
Chan[n] : ADC raw [0] : 077e [3] : 0098 [6] : 00ce

I (12006) ADC/DAC: 7f 07 30 70 80 61 e3 33 7e 07 31 70 80 61 e3 33
Chan[n] : ADC raw [0] : 077f [3] : 03e3 [6] : 0180 [7] : 0030

I (13006) ADC/DAC: 80 07 4f 70 8f 61 f2 33 7f 07 4f 70 8f 61 f0 33
Chan[n] : ADC raw [0] : 0780 [3] : 03f2 [6] : 018f [7] : 004f

I (14006) ADC/DAC: 7e 07 62 70 93 61 fa 33 7f 07 62 70 96 61 fa 33
Chan[n] : ADC raw [0] : 077e [3] : 03fa [6] : 0193 [7] : 0062

I (15006) ADC/DAC: 7d 07 31 70 71 61 e1 33 80 07 32 70 70 61 e0 33
Chan[n] : ADC raw [0] : 077d [3] : 03e1 [6] : 0171 [7] : 0031

I (16006) ADC/DAC: e7 33 e7 33 e7 33 e7 33 e7 33 e7 33 e7 33 e7 33
Chan[n] : ADC raw [3] : 03e7

I (16506) tcpip_adapter: sta ip: 192.168.252.140, mask: 255.255.255.192, gw: 192.168.252.129
I (16506) wifi station: got ip:192.168.252.140
I (17006) ADC/DAC: e7 33 e7 33 e7 33 e7 33 e7 33 e7 33 e7 33 e7 33
Chan[n] : ADC raw [3] : 03e7

I (18006) ADC/DAC: e7 33 e7 33 e7 33 e7 33 e7 33 e7 33 e7 33 e7 33
Chan[n] : ADC raw [3] : 03e7

You can see at first we get all the channels and then once Wifi is re-established, we stop reading
data from the ADC.
Michael

@negativekelvin
Copy link
Contributor

@mishafarms thanks, I am able to reproduce. However adding one thing seems to resolve it:
esp_wifi_set_ps(WIFI_PS_NONE);
So wifi powersave is the problem

@mishafarms
Copy link
Author

@negativekelvin You have found a workaround. Thank you. I think I can live without
powersave.

Michael

@koobest
Copy link
Contributor

koobest commented Jul 17, 2019

When using WIFI, if the power saving mode is not used, the SAR power domain will be turned off when entering the power saving mode to reduce power consumption. This is the root cause of this problem. The current solution is to set WIFI to WIFI_PS_NONE mode.

@negativekelvin
Copy link
Contributor

I think you mean

When using WIFI, if the power saving mode is not used, the SAR power domain will be turned off when entering the power saving mode to reduce power consumption.

So will there be a way for the user app to take a lock to prevent this while still using powersave?

@igrr
Copy link
Member

igrr commented Jul 17, 2019

Yes, we will implement this.

@koobest
Copy link
Contributor

koobest commented Jul 18, 2019

@negativekelvin
Yes, as you said, I made the logic wrong : b
Correct it:
When using WIFI, if the power saving mode is used, the SAR power domain will be turned off when entering the power saving mode to reduce power consumption.

@tony-ward
Copy link

Thank you guys, we will implement this workaround asap!

@giPeteR
Copy link

giPeteR commented Aug 2, 2019

@negativekelvin
...adding one thing seems to resolve it:
esp_wifi_set_ps(WIFI_PS_NONE);

THANKS! Now everything works.
I know I turned off power save for ADC and I2S, but obviously WiFi rules them all :(
It seems you have to put esp_wifi_set_ps(WIFI_PS_NONE); right after esp_wifi_init() but before i2s_init(). Meaning, you cannot start or init I2S before WiFi.

(I wonder what happens at a reconnect? Will it remember WIFI_PS_NONE?)

@wammaw1314
Copy link

@negativekelvin I also encountered this problem, using your solution esp_wifi_set_ps(WIFI_PS_NONE);, the DMA ADC can read the normal value without restarting the device.
However, after executing esp_restart();, the device DMA ADC is read-only to a zero value.
And I reset the device by ESP32 reset IO, then the result is normal.

ESP-IDF Version: v4.1-dev-815-ga45e998-dirty
Development Kit: ESP32-DevKitC
Operating System: Ubuntu 14.04 x86_64
Power Supply: USB

The full code
Copy your ESP_IDF example structure:
examples\peripherals\i2s_adc_dac\main\app_main.c
and replace everything in app_main.c with this:
app_main.zip

@negativekelvin
Copy link
Contributor

#3973

@Alvin1Zhang
Copy link
Collaborator

@mishafarms #3973 has been fixed, would you please help try the fix mentioned in there? Thanks.

@tom-borcin
Copy link
Collaborator

Hi @mishafarms,

we think the issue is fixed now and therefore we are closing it to keep our backlog manageable. If you don't agree with this decision, please let me know.

Thank you,

Tomas

@DarmorGamz
Copy link

December 2023 this issue persists on the Esp32s3 ESP_IDF v5.1.1

esp_wifi_set_ps(WIFI_PS_NONE) is irrelevant

Order of ADC Init and WIFI Init are also irrelevant, anytime the esp_wifi_start() is called, and the ADC1 continuous is running, the DMA buffer stops being updated.
adc_continuous_start() must be called AFTER esp_wifi_start(), however in my application esp_wifi_start() and esp_wifi_stop() are called frequently which makes this issue prominent.

I can provide code and logs as requested

@expresspotato
Copy link

expresspotato commented Sep 20, 2024

I second that this issue is still present, or was regressed back into v4.4.8. Once WiFi is started and a scan initialized, interrupts no longer work on GPIO 36 or GPIO39. Reading the value of the pin itself with a scope or in software with gpio_get_level every 10ns is high on the LyraT v4.3 board.

Something is definitely wrong with WiFi and these two pins, that is not just the 80ns burst low as specified in the errata.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests