Hallo Leeutz, ich habe seit mehreren Tagen das Problem das allen Anschein nach die SPI Verbindung zwischen Teensy und ESP mir meine Audio PCM Daten (im wahrsten sinne) zersägt.
Zum vorhaben:
Ich würden gerne Audio Daten die der Teensy empfängt via SPI zum ESP und auch zurück schaffen. Dann die Daten via WebSocket zum Browser schicken kann, damit ich diese dann dort Visualisieren und ausgeben kann.
Das verwendetet ESP Modul. ist der ESP-M1 Modul, darauf befindet sich ein ESP8285, das sollte aber keinen unterschied machen zum ESP8266.
Es ist nun so, das der Weg vom Browser zum Teensy hin perfekt funktioniert, da kommt ein schöner Sinus am DAC heraus.
Aber der Weg vom Teensy zum Browser ist nur noch ein gerausche und Getöse. Wie bei einem Schlecht eingestellten Radio Sender. Siehe Bild:
Das Bild soll einen 400Hz Sinus Darstellen.
PCM Daten sind ja nur Messwerte zum Zeitpunkt x mit der Amplitude x.
Die einzige stelle wo die PCM Daten derartig durcheinander geraten können ist die SPI Verbindung.
Weil das ganze nun etwas umfangreicher ist habe ich den Code bis auf ein Minimum heruntergeschraubt.
Der Teensy ist in in meinen Fall das Slave Device. Als Transfer Methode habe ich 16bit wide transfers.
Die verwendete Lib ist diese:
Mehr infos dazu finde ich auch nicht außer diesen Foren Eintag.
Für den Test habe ich am Teensy eine (SPI Schleife) gemacht. Sprich: der Teensy Kopiert den Empfangen Wert und sendet diesen zurück.
#include <SPI.h>
#include "TSPISlave.h"
#define ESP_READY_PIN 39
#define SPI_READY_PIN 35
#define MISO_PIN 1
#define MOSI_PIN 0
#define SCK_PIN 32
#define CS_PIN 31
TSPISlave mySPI = TSPISlave(SPI1, MISO_PIN, MOSI_PIN, SCK_PIN, CS_PIN, 16);
bool showcnt = false;
bool receiveSPIaudio = false;
unsigned long previousMillis = 0;
volatile uint16_t wert = 0;
volatile uint16_t cnt = 0;
unsigned long endTime = 0;
bool isSDCardReady = false;
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(ESP_READY_PIN, INPUT);
pinMode(SPI_READY_PIN, INPUT);
mySPI.onReceive(mySPIFunc);
attachInterrupt(digitalPinToInterrupt(SPI_READY_PIN), toggleSPIInput, CHANGE);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 700) {
previousMillis = currentMillis;
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
Serial.println(wert, DEC);
}
if (showcnt) {
Serial.print("Zähler: ");
Serial.println(cnt, DEC);
Serial.print("Zeit: ");
Serial.println(endTime);
Serial.println();
cnt = 0;
endTime = 0;
showcnt = false;
}
}
void toggleSPIInput() {
if (digitalReadFast(SPI_READY_PIN) == LOW)//WiFi Modul verbunden
{
wert = 0;
receiveSPIaudio = true;
} else {//SPI verbindung beendet
wert = 0;
receiveSPIaudio = false;
}
}
//wird aufgerufen wenn SPI cs pin == LOW
FASTRUN void mySPIFunc() {
unsigned long startTime = micros();
while (mySPI.active() ) {
if (mySPI.available()) {
cnt++;
wert = mySPI.popr();
mySPI.pushr(wert);
}
}
endTime = micros() - startTime;
showcnt = true;
}
Die Ausgabe am teensy ist dann wie Folgt:
64624
Zähler: 131
Zeit: 794
16270
Zähler: 130
Zeit: 793
59384
Zähler: 129
Zeit: 795
51040
Zähler: 131
Zeit: 794
65310
Zähler: 130
Zeit: 794
63738
Zähler: 130
Zeit: 800
16128
Zähler: 131
Zeit: 794
58352
Zähler: 131
Zeit: 795
63744
Zähler: 131
Zeit: 794
61960
Zähler: 129
Zeit: 793
32664
Zähler: 130
Zeit: 794
3065
Zähler: 128
Zeit: 794
37248
Zähler: 131
Zeit: 795
Der Zähler wert ist hier schon falsch, ich tätige jeweils nur 128 Übertragungen.
Der ESp, als SPI Master hat diesen code:
#include <ESP8266WiFi.h>
#include "SPI.h"
extern "C" {
#include "osapi.h"
#include "ets_sys.h"
#include "user_interface.h"
}
#define WEBSOCKETS_SERVER_CLIENT_MAX (1)
#define ESP_READY_PIN 0
#define SPI_READY_PIN 2
#define ESP_READY_PIN_LED 4
#define WiFi_LED_PIN 5
#define SPI_SPEED 1000000
#define HTTP_PORT 80
#define SOCKET_PORT 81
#define DNS_PORT 53
#define AUDIO_BLOCK_SAMPLES 128
#define INTERVAL 700*1000
const uint8_t wifiChannels[6] = {1, 5, 6, 7, 9, 13};
SPISettings settingsSPI(1000000, MSBFIRST, SPI_MODE0);
unsigned long previousMillis = 0;
uint8_t client_id = NULL;
bool wifiLED_Status = false;
uint8_t displayData[9] = {0};
unsigned long previousMicros = 0;
uint16_t xy = 0;
uint16_t wert = 0;
uint16_t inWert = 0;
void IRAM_ATTR spi_audio() {
unsigned long currentMicros = micros();
if (currentMicros - previousMicros >= INTERVAL) {
previousMicros = currentMicros;
SPI.beginTransaction(settingsSPI);
digitalWrite(SS, LOW); // enable Slave Select
for (byte i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
wert += 1;
inWert = SPI.transfer16(wert);
if (inWert != wert - 2) {
xy++;
}
}
digitalWrite(SS, HIGH); // disable Slave Select
SPI.endTransaction();
if (xy > 0) {
Serial.print("SPI Fehler: ");
Serial.println(xy);
Serial.print("Wert: ");
Serial.println(inWert);
xy = 0;
}
}
}
void setup() {
//SYS_CPU_160MHZ 160MHz
system_update_cpu_freq(SYS_CPU_160MHZ);
system_timer_reinit();
delay(6000);
pinMode(SPI_READY_PIN, OUTPUT);
pinMode(ESP_READY_PIN, OUTPUT);
pinMode(ESP_READY_PIN_LED, OUTPUT);
pinMode(WiFi_LED_PIN, OUTPUT);
digitalWrite(ESP_READY_PIN_LED, HIGH);
digitalWrite(WiFi_LED_PIN, LOW);
Serial.begin(115200);//or 115200
SPI.pins(14, 12, 13, 15);
SPI.setHwCs(false);
SPI.begin();
SPI.setFrequency(SPI_SPEED);
pinMode(SS, OUTPUT);
digitalWrite(SS, HIGH); // disable Slave Select
ESP.eraseConfig(); // Alte WiFi Konfiguration löschen
WiFi.persistent(false);
WiFi.disconnect(true);
WiFi.softAPdisconnect();
WiFi.mode(WIFI_OFF);
wifi_set_sleep_type(NONE_SLEEP_T);//maximale sendleistung
bool writeIncommingData = false;
byte line = 0;
String _SSID = "abcdef";
String _PASSWD = "0123456789";
digitalWrite(SPI_READY_PIN, HIGH);
digitalWrite(ESP_READY_PIN, LOW);
const int randNr = random(0, 5);
const byte WiFi_ChannelNr = wifiChannels[randNr];
WiFi.mode( WIFI_AP);
WiFi.setOutputPower(10.0);
WiFi.setPhyMode(WIFI_PHY_MODE_11G);
_SSID.trim();
_PASSWD.trim();
// ss->println(_SSID);
// ss->println(_PASSWD);
if (_SSID.length() > 32 || _SSID.length() < 4) {
while (1) {
delay(100);
}
}
if (_PASSWD.length() > 64) {
while (1) {
delay(100);
}
}
if (_PASSWD.length() >= 8) {
WiFi.softAP(_SSID, _PASSWD, WiFi_ChannelNr, false, 1);
} else {
WiFi.softAP(_SSID, "", WiFi_ChannelNr, false, 1);
}
WiFi.setAutoReconnect(true);
WiFi.setAutoConnect(false);
IPAddress IP = WiFi.softAPIP();
}
void loop() {
spi_audio();
}
Die Ausgabe ist dann wie Folgt:
Wert: 29948
SPI Fehler: 91
Wert: 30462
SPI Fehler: 76
Wert: 15230
SPI Fehler: 78
Wert: 15358
SPI Fehler: 73
Wert: 15486
SPI Fehler: 66
Wert: 31228
SPI Fehler: 93
Wert: 32126
SPI Fehler: 96
Wert: 31740
SPI Fehler: 89
Wert: 31998
SPI Fehler: 51
Wert: 16126
SPI Fehler: 106
Wert: 32510
SPI Fehler: 78
Wert: 16382
SPI Fehler: 56
Wert: 16510
SPI Fehler: 42
Wert: 16638
SPI Fehler: 111
Wert: 33532
SPI Fehler: 50
Wert: 16894
SPI Fehler: 91
Wert: 34430
SPI Fehler: 65
Wert: 17150
SPI Fehler: 92
Wert: 34558
SPI Fehler: 81
Wert: 17406
SPI Fehler: 79
Wert: 17534
SPI Fehler: 94
Von der Sache her ist ja MiSO und MOSI syncron je nach Data Mode.
Wie so muss ich den aber dann zwei Inkrementirungen abzihen?
if (inWert != wert - 2) {
Sollte es nicht -1 sein?
Gut ok, sind eben 16 Bit transfers also 2* 8Bit
Übertrrage ich eien Statischen wert z.B 1234 habeich keinen SPi Fehler. Nur den Ersten der allerersten Aussendung. Auch Komisch.
Setze ich den transfer auf 8 Bit. Dann habe ich nur noch einen SPI Fehler in jedem Schleifendurchgang und muss aber trotzdem noch 2 vom wert Subtrahieren. Bei 8 Bit stimmt dann der auch der Zählerwert am teensy.
Micht Stört jezt hier dieser versatz von zwei schleifendurchgängen / aussendung. Sowohl bei 8 Bit also auch bei 16 bit.
Und weshalb geht die Übetragung in richtung teensy?
Teensy und ESP sind auf eiener PCB Platien verlötet, also eine Fehlerahfte Masse odder Verbindung ist ausgeschlossen.
in der ESP SPi Lib wird der 16 bit wert in zwei 8 Bit werte Zerlegt:
Der Teensy Möchte aber mit eienr Sendung einen 16bit wert loswerden. Ich glaube das ist das Problem.
....
Ich weis mir ist nicht mehr zu helfen, aber villeicht hat wenigstens einer eine Idee