Skocz do zawartości

Sipeed Tang Nano 4k z ADC - Gowin FPGA Designer


Gieneq

Pomocna odpowiedź

4 minuty temu, FlyingDutch napisał:

Odnośnie drugiego tematu, to może warto spróbować zainstalować na ESP32 RTOS'a

Przecież framework Arduino to nakładka na RTOS... Kurka wodna, ludzie, zacznijcie jakieś dokumentacje czytać albo co...

  • Lubię! 2
Link do komentarza
Share on other sites

Myślę że używanie takich funkcji jest dość sugestywne:

xTaskCreatePinnedToCore(core0_task, "FFT_processor", 64000, NULL, 1, NULL, 0);

Coś kojarzyłem czytając komentarze tego typu:

Cytat

If you use Arduino-ESP32, you automatically have FreeRTOS available. In fact, the user-implemented setup() and loop() functions are run in a FreeRTOS task

Tylko pytanko @ethanak jaka jest różnica w wydajności używając frameworku arduino nabudowanego na FreeRTOS od tego co np. jest w poradnikach jak ten z YT co wrzuciłem? Czy ewentualnie jest jakaś inna różnica której nie jestem świadom?

Link do komentarza
Share on other sites

Ciekawe 🙂 Orientujesz się może jak wygląda implementacja tego mechanizmu? Bo trochę przypomina to timer aktualizujący w sposób nieblokujący wskaźniki na funkcje.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Chodzi o fizyczną implementację czy ogólną zasadę?

Jeśli ogólną, jest to po prostu "wielozadaniowość bez wywłaszczania" - dany task będzie się wykonywał dopóki nie zezwoli na przełączenie (delay, yield) albo nie zostanie usunięty. W takiej sytuacji scheduler sprawdzi, czy jakiś inny task nie czeka na uruchomienie i jeśli tak, przekazuje do niego sterowanie. Zresztą - pewnie @Elvis będzie mógł powiedzieć coś więcej.

A implementacje masz w źródłach na dysku - nie czytałem, bo dłuższe i nudniejsze niż "man bash" 🙂

Edytowano przez ethanak
Link do komentarza
Share on other sites

@Gieneq Przełączanie zadań raczej nie ma zbyt wiele wspólnego ze wskaźnikami do funkcji, bo funkcje zawsze rozpoczynają działanie od początku, nie zachowują też wartości zmiennych lokalnych. Jest natomiast podobne do obsługi przerwania - przełączanie zadań działa jak przerwanie, tylko przy powrocie z przerwania może być wznowiony inny wątek.

  • Lubię! 1
  • Pomogłeś! 1
Link do komentarza
Share on other sites

Cześć,

wczoraj poczytałem o protokole I2S i jest on tak prosty, że nawet bez żadnego specjalizowanego IP Core (układ FPGA) bardzo łatwo jego obsługę będzie zaimplementować w języku Verilog. Poza tym przetwornik ADC z I2S zapewnia dużo większą prędkość zbierania sampli sygnału audio w porównaniu do przetwornika opartego na układzie ADS1256. Dzisiaj będę próbował podłączyć przetwornik z I2S do ESP32, zebrać sample przebiegu audio i policzyć z nich FFT programem opisywanym we wcześniejszych postach.

Ponieważ w tanim module przetwornika ADC opartego na układzie scalonym PCM1808 (TI) jest użyty przetwornik ADC typu delta-Sigma, postanowiłem trochę odświeżyć swoją wiedzę teoretyczną dotyczącą zasady działania tego typu przetwornika. Ponieważ wyszukanie wartościowych informacji w sieci wymaga trochę czasu, a ja przeprowadziłem takie rozeznanie zamieszczam linki, które mogą się komuś przydać. Tutaj link do karty katalogowej przetwornika ADC PCM18078:

https://www.ti.com/lit/ds/symlink/pcm1808-q1.pdf?ts=1646903155249&ref_url=https%3A%2F%2Fwww.ti.com%2Fproduct%2FPCM1808-Q1

Pod tym linkiem bardzo proste opisanie zasady działania przetwornika ADC typu Delta-Sigma:

https://www.allaboutcircuits.com/technical-articles/understanding-the-delta-sigma-analog-to-digital-converter/

A tutaj linki z wytłumaczeniem parametrów i właściwości działania przetworników analogowo-cyfrowych (podstawowej pojęcia):

https://www.allaboutcircuits.com/technical-articles/understanding-analog-to-digital-converters-deciphering-resolution-and-sampl/

https://www.allaboutcircuits.com/technical-articles/understanding-the-dynamic-range-specification-of-an-ADC/

https://www.allaboutcircuits.com/technical-articles/understanding-amplitude-quantization-error-analog-digital-converters/

https://www.allaboutcircuits.com/industry-articles/understanding-effective-noise-bandwidth-in-precision-delta-sigma-adc-part-4/

https://www.allaboutcircuits.com/technical-articles/understanding-analog-to-digital-converters-the-successive-approximation-reg/

https://www.ti.com/lit/an/slyt423a/slyt423a.pdf?ts=1646830079048&ref_url=https%3A%2F%2Fwww.google.com%2F

Pozdrawiam

 

Edytowano przez FlyingDutch
  • Lubię! 1
  • Pomogłeś! 1
Link do komentarza
Share on other sites

22 godziny temu, FlyingDutch napisał:

Pod tym linkiem bardzo proste opisanie zasady działania przetwornika ADC typu Delta-Sigma:

@FlyingDutch przewidziałeś to czego potrzebuję 🙂 wczoraj czytałem notę katalogową układu ADS1256 i chciałem dowiedzieć się czegoś więcej o przetworniku.

  • Lubię! 1
Link do komentarza
Share on other sites

3 godziny temu, Gieneq napisał:

@FlyingDutch przewidziałeś to czego potrzebuję 🙂 wczoraj czytałem notę katalogową układu ADS1256 i chciałem dowiedzieć się czegoś więcej o przetworniku.

Cześć @Gieneq,

wczoraj cały dzień studiowałem teorię dotyczącą przetworników ADC Delta-Sigma, dzisiaj będę próbował podłączyć płytkę z przetwornikiem PCM1808 do ESP32 i napisać program do zbierania sampli i liczenia FFT.

Update: przestudiowałem kartę katalogową układu PCM1808, oraz dokument dot. "Evaluation board for PCM1808" i wiele rzeczy się wyjaśniło - patrz linki:

https://www.ti.com/lit/ds/symlink/pcm1808-q1.pdf?ts=1646903155249&ref_url=https%3A%2F%2Fwww.ti.com%2Fproduct%2FPCM1808-Q1

https://www.ti.com/lit/ug/sbau349/sbau349.pdf?ts=1646902998444&ref_url=https%3A%2F%2Fwww.google.com%2F

Nadal mam dwie wątpliwości odnośnie podłączenia płytki z PCM1808 do ESP32. Najpierw schemat "Evaluation board":

PCM1808_Schematic.thumb.png.5ec37de7b840753d8733b33d7fbd4fdd.png

Można z niego dużo ustalić. Teraz jak ustawić wejścia decydujące w jakim trybie będzie pracował układ PCM1808:

PCM1808_ustawienia.thumb.png.5e37d8e39b6e27f5d340c51fb1722fbd.png

Tutaj pinout układu PCM1808 (z opisem wejść/wyjść);

PCM1808_Pinout.thumb.png.4528d604f6b46bf99bd8b112d27a3b2f.png

A tutaj częstotliwości zegara wejściowego dla układu PCM1808:

PCM1808_Clock.thumb.png.ea918c549378a6c4733f2c5ab25e511a.png

Z tego ostatniego wynika, że aby układ pracował jako Master o częstotliwości próbkowania 44,1 Khz (z Fs*256) na wejście SCKI powinien być podany zewnętrzny zegar o częstotliwości 11.2896 MHz. Nie wiem tylko co z pinem BCK (Bit Clock), czy na BCK powinien być podany zegar o częstotliwości 44,1 KHz*24 = 1 058 400 Hz , czy też ten zegar będzie wygenerowany automatycznie z zegara na pinie SCKI przez układ PCM1808 ?

Pozdrawiam

 

Pozdrawiam

Edytowano przez FlyingDutch
  • Lubię! 1
Link do komentarza
Share on other sites

Cześć,

próbuję wygenerować sygnał prostokątny o częstotliwości 11 MHz(dokładnie  11.2896MHz)- zegar dla układu PCM1808 na ESP32. jedyny kod jak to zrobić znalzłem dla środowiska "Expressif IDE" - patrz link:

https://www.esp32.com/viewtopic.php?t=1037

Musiałem go trochę zmodyfikować i dodać kilka plików nagłówkowych z Githuba, aby dał się skompilować w "Arduino IDE", ale się udało i kompiluje się bez błędów. Tutaj program główny dla Arduino:

#include "FFT.h" // include the library
#include "FFT_signal.h"
#include <SPI.h>
#include <ADS1256.h>
#include "ledc.h"

#define BIT_NUM 2

float clockMHZ = 7.68; // crystal frequency used on ADS1256
float vRef = 2.5; // voltage reference

// Construct and init ADS1256 object
ADS1256 adc(clockMHZ,vRef,false); // RESETPIN is permanently tied to 3.3v

float sensor1;
bool startSampling=false;
bool endSampling=false;
bool meTime=false;
volatile int licSample=0;
long int t1A=0L;
long int t2A=0L;

void setup() { //---------------------------------------------------------------------------------------
  Serial.begin(115200); // use the serial port
  Serial.println("Starting ADC");

  ledc_timer_config_t ledc_timer;
  ledc_channel_config_t ledc_channel;
  
  //params ledc_timer
  ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
  ledc_timer.timer_num  = LEDC_TIMER_0;
  ledc_timer.bit_num    = (ledc_timer_bit_t) LEDC_TIMER_2_BIT; //LEDC_TIMER_2_BIT;
  ledc_timer.freq_hz    = 2000000;
  
  //params ledc_channel
  ledc_channel.channel    = LEDC_CHANNEL_0;
  ledc_channel.gpio_num   = 14;  //WAS 18
  ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
  ledc_channel.timer_sel  = LEDC_TIMER_0;
  ledc_channel.duty       = 2;

  //Generacja zegara dla PCM1808
  ledc_timer_config(&ledc_timer);
  ledc_channel_config(&ledc_channel);

  // start the ADS1256 with data rate of 15 SPS and gain x1
  adc.begin(ADS1256_DRATE_30000SPS,ADS1256_GAIN_1,false); 

  Serial.println("ADC Started");
  // Set MUX Register to AINO so it start doing the ADC conversion
  Serial.println("Channel set to Single end ch0");
  adc.setChannel(0);
  licSample=0;
  startSampling=true; 
  meTime=true; 
}//---------------------------------------------------------------------------------------

void loop() {

  if (startSampling) {
   if (meTime) {
    t1A=micros();
    meTime=false;
   }
   adc.waitDRDY(); // wait for DRDY to go low before next register read
   sensor1 = adc.readCurrentChannel(); // read as voltage according to gain and vref
  
   //Serial.println(sensor1 , 10); // Print as decimal, 10 decimal places
   fft_signal[licSample]=(double)sensor1;
   licSample++;
   if (licSample>=256) {
     licSample=0;
     startSampling=false;
     endSampling=true;
     t2A=micros();
     Serial.print("Time taken: ");
     Serial.print((t2A-t1A)*1.0/1000);
     Serial.println(" milliseconds!");
   }
  }

  if (endSampling) {
    char print_buf[300];
    fft_config_t *real_fft_plan = fft_init(FFT_N, FFT_REAL, FFT_FORWARD, fft_input, fft_output);
  
    for (int k = 0 ; k < FFT_N ; k++)
      real_fft_plan->input[k] = (float)fft_signal[k];
  
    long int t1 = micros();
    // Execute transformation
    fft_execute(real_fft_plan);

    //sprintf(print_buf,"sizeFFT= %d", real_fft_plan->size);
    //Serial.println(print_buf);

    long int t2 = micros();
    
    // Print the output
    for (int k = 1 ; k < real_fft_plan->size / 2 ; k++)
    {
      /*The real part of a magnitude at a frequency is followed by the corresponding imaginary part in the output*/
      float mag = sqrt(pow(real_fft_plan->output[2*k],2) + pow(real_fft_plan->output[2*k+1],2))/1;
      float freq = k*1.0/(1*TOTAL_TIME);
      sprintf(print_buf,"%f Hz : %f", freq, mag);
      Serial.println(print_buf);
      if(mag > max_magnitude)
      {
          max_magnitude = mag;
          fundamental_freq = freq;
      }
    }   
    
    Serial.println();
    /*Multiply the magnitude of the DC component with (1/FFT_N) to obtain the DC component*/
    sprintf(print_buf,"DC component : %f g\n", (real_fft_plan->output[0])/10000/FFT_N);  // DC is at [0]
    Serial.println(print_buf);
  
    /*Multiply the magnitude at all other frequencies with (2/FFT_N) to obtain the amplitude at that frequency*/
    sprintf(print_buf,"Fundamental Freq : %f Hz\t Mag: %f g\n", fundamental_freq, (max_magnitude/10000)*2/FFT_N);
    Serial.println(print_buf);
  
    Serial.print("Time taken: ");Serial.print((t2-t1)*1.0/1000);Serial.println(" milliseconds!");
    
    // Clean up at the end to free the memory allocated
    fft_destroy(real_fft_plan);
    endSampling=false;
    }
  
}

Program wykonuje się bez błędów, ale zamiast przebiegu prostokątnego o f= 2MHz jest generowana jakaś sieczka - patrz zrzut ekranu z oscyloskopu:

ZegarESP3201.thumb.png.5943118a95738ef67f6f2f2f2364cb40.png

Mógłby mi ktoś podpowiedzieć co jest nie tak z istniejącym kodem, lub polecić inny sposób na wygenerowanie przebiegu prostokątnego o wypełnieniu 50 % i częstotliwości 11 MHz (na ESP32).

W zipie kod całego projektu (łącznie z plikami nagłówkowymi).

FFT_on_ESP32_PCM1808_01.zip

Pozdrawiam

Link do komentarza
Share on other sites

Cześć,

nadal walczę z wygenerowaniem zegara 11 Mhz dla układu PCM1808 na płytce ESP32 (ESP-WROVER). chyba nie zostanę fanem ESP32. Dlaczego:

1) Po pierwsze wszystkie przykłady jakie udaje mi się znaleźć są dla środowiska "ESP-IDF" (command line), aby je uruchomić na "Arduino IDE" trzeba szukać i dołączać sporo plików nagłówkowych

2) Środowisko "ESP-IDF" ma duzo zależności dla mnie problematycznych (np. inna wersja Python niż, mam zainstalowaną)

3) Przykłady, które się kompilują w "Arduino IDE" (co wymagało sporo pracy) słabo działają.

Próbuję wygenerować sygnał prostokątny o częstotliwości 11 MHz korzystając z "LEDC" - patrz link:

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/ledc.html

W "Arduino IDE" wyizolowałem kod do tego celu - patrz poniżej:

#include "ledc.h"


void setup() { //---------------------------------------------------------------------------------------
  Serial.begin(115200); // use the serial port
  Serial.println("Starting ADC");

  ledc_timer_config_t ledc_timer;
  ledc_channel_config_t ledc_channel;
  
  //params ledc_timer
  ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;//LEDC_HIGH_SPEED_MODE;
  ledc_timer.timer_num  = LEDC_TIMER_0;
  ledc_timer.bit_num    = (ledc_timer_bit_t) LEDC_TIMER_1_BIT; //LEDC_TIMER_2_BIT;
  ledc_timer.freq_hz    = 1000000;
  ledc_timer.clk_cfg    = LEDC_USE_APB_CLK;
  
  //params ledc_channel
  ledc_channel.channel    = LEDC_CHANNEL_0;
  ledc_channel.gpio_num   = 18;  //WAS 18
  ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
  ledc_channel.timer_sel  = LEDC_TIMER_0;
  ledc_channel.duty       = 1;

  //Generacja zegara dla PCM1808
  ledc_timer_config(&ledc_timer);
  ledc_channel_config(&ledc_channel);

  Serial.println("Program Started");
  
}//---------------------------------------------------------------------------------------

void loop() {
  
}

Gdy ustawiałem częstotliwość 11 Mhz, to jest już na granicy możliwości mojego oscyloskopu. Gdy ustawiam częstotliwość przebiegu (jak w kodzie powyżej) 1 Mhz - to jeszcze jakoś mogę ten przebieg obejrzeć, ale jest to sinusoida o amplitudzie poniżej 1-go wolta. Nie mogę tego przebiegu obejrzeć na analizatorze logicznym, bo amplituda przebiegu jest za mała, aby wyzwolić rejestrację przebiegu. Program jest raczej poprawny, skąd taki wniosek: otóż gdy ustawiałem dużo niższą częstotliwość (powiedzmy 4 KHz) i większą rozdzielczość timera (14-bit), to gdy zmieniałem wypełnienie to było to prawidłowo widoczne na oglądanym przebiegu na oscyloskopie, ale amplituda przebiegu nadal była około 1-go wolta.

Ma ktoś jakieś pomysły jak wygenerować ten sygnał prostokątny 11 MHz na ESP32? Jak nic nie znajdę to wygeneruję taki sygnał na układzie FPGA, tam jest to proste do zrobienia.

Pozdrawiam

 

Link do komentarza
Share on other sites

W ogóle w jaki układ ESP celujemy? Dziś YT podpowiedział mi filmik o M5stack z ESP32-C3 i trochę się zastanawiam.

C3 z RISC-V ma 1 rdzeń i 160 MHz. 2x droższy S3

image.thumb.png.85b8f2ed7ac9f951b793137e48d5427a.png

Z tego wykresu wychodzi że nieważne co, lepiej 2 rdzenie:

image.thumb.png.016739d5b9607902d688bdab57e9d119.png

Ale czytając to wpadłem na pomysł, który trochę burzy @FlyingDutch  twoje testy 😞 

Cytat

If we really needed to crush floats, we’d go for a chip that’s better suited for the task like an STM32F4xx or STM32F7xx, or those brutal NXP/Freescale 600 MHz i.MX ARM7 chips in the Teensy 4.0.

Na 2 stronach wykresy (ten i ten) mocy CoreMark są imponujące:

image.thumb.png.2602dc20d99456b4ef090825c0cb0c73.pngimage.thumb.png.7db6f9f776610e9fb36fae364bfe204f.png

Drogie to, ale wygląda jakby służyło właśnie do tego projektu.

image.thumb.png.e9ccecdf34000d0cbbca8ea4fd6d0908.png

Więc moja propozycja, tylko znowu inny sprzęt... eh, chyba dlatego robi sie zawsze research przed podjęciem zakupów. Może ESP32 tylko do WiFi, a wszystko dać na Teesy 4.1?

 

Link do komentarza
Share on other sites

2 godziny temu, Gieneq napisał:

W ogóle w jaki układ ESP celujemy? Dziś YT podpowiedział mi filmik o M5stack z ESP32-C3 i trochę się zastanawiam.

 tego wykresu wychodzi że nieważne co, lepiej 2 rdzenie:

image.thumb.png.016739d5b9607902d688bdab57e9d119.png

Ale czytając to wpadłem na pomysł, który trochę burzy @FlyingDutch  twoje testy 😞 

Na 2 stronach wykresy (ten i ten) mocy CoreMark są imponujące:

 

Więc moja propozycja, tylko znowu inny sprzęt... eh, chyba dlatego robi sie zawsze research przed podjęciem zakupów. Może ESP32 tylko do WiFi, a wszystko dać na Teesy 4.1?

Cześć @Gieneq,

ja mam ESP32-WROVER - chyba jeden z najczęściej spotykanych modeli. Ten kod powinien działać, bo w kilku miejscach widziałem praktycznie identyczny, no i opis API to potwierdza. Nie wiem co robię nie tak, i najdziwniejsze jest to, że dla mniejszych częstotliwości jest generowany prostokąt, tylko o amplitudzie mniejszej od 1-go wolta. Ja byś znalazł jakiś kod dla ESP32 dla Arduino jak wygenerować prostokąt o większej częstotliwości to daj znać. Mam jeszcze jadną identyczna płytkę ESP32, ale ta druga nie daje się zaprogramować (problem z połączeniem USB, nie pojawia się żaden port).

Pozdrawiam

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.