• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

für xorg1990

tsseh schrieb:
wenn du die 3000 byte immer im block zum esp sendest und dann diesen block auf dem esp nochmal in 128 byte blöcke unterteilst und zum avr sendest sollte das doch gehen. hast halt ne halbe sekunde Verzögerung drin
Nee leider geht das auch nicht, da selbst wenn ich einen 3000byte großen Puffer zum esp sende und exakt diesen wider zurücksende dauert es zu lange. im Browser läuft der puffer über. Der Code ist denkbar einfach.
Außerdem kommt kein onmessage event wenn der zu sendete Puffer größer ist als 1024byte.

Code:
var bufferSize = 16384;
var chunkSize = 128;
		var sendTime = 0;
		let canTransmit = false;
		let Uint8Buf = new Uint8Array(bufferSize*4);
var bufferMask = Uint8Buf.length-1;

	resampler.resampleOutput = function(output){
			if(connected){
			 for (let i=0;i<output.length;i++){
			 	let next = ((w_ptr + 1) & bufferMask);
			 	if (r_ptr == next){
					console.log("buffer voll");
			 		break;
			 	}
			 	let filterSample = FirFilter.pushSample(output[i]);
		        let s = Math.max(-1, Math.min(1, filterSample));
		        s = parseInt(s*127+128);
		        Uint8Buf[w_ptr] = s;
		        w_ptr=next;
		        if(next == chunkSize && canTransmit == false){
		        	canTransmit == true;
		        	transmit();
		        }
			}
		}
	}

function transmit(){
		var subBuffer = Uint8Buf.subarray(r_ptr,r_ptr+chunkSize);
			 if (r_ptr == w_ptr){
			 	console.log("buffer leer");
			 	return;
			 }
			r_ptr = (r_ptr+chunkSize) & bufferMask;
			sendTime = performance.now();
			WsConnection.send(subBuffer);
	}

	function handleOnmessage(e){
			var rtime = performance.now() - sendTime;
			console.log(rtime);
			transmit();
			//console.log(e.data.byteLength);
		}
aufm esp:
Code:
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
    switch(type) {
        case WStype_DISCONNECTED:
           Serial.println("Disconnected");
            break;
        case WStype_CONNECTED:
            {
                IPAddress ip = webSocket.remoteIP(num);
            }
            break;
        case WStype_BIN:
            // send message to client
            webSocket.sendBIN(num, payload, length);
            break;
    }

}
Wenn diese Bedingung erfüllt ist, wird der Prozess in Gang gebracht:
next == chunckSize && canTransmit == false
Irgendwann kommt dann console.log("buffer voll");

tsseh schrieb:
die ~100 ms waren für die 128byte blöcke? wächst das in etwa linear an wenn du 1024 byte blöcke nimmst?
Die ~100ms sind für die 128 blöcke -richtig.
Ja da wächst was linear an und zwar das senden vom esp zum Browser hin bei 1024byte großen Blöcken kommen die Events total unregelmäßig. Bis sogar die Socket Verbindung geschlossen wird "invalid frame..irgendwas". Bei 128-512 großen Blöcken kommt der Message event viel regelmäßiger, keine ausfälle.

Da habe ich jetzt festgestellt, da ich nun eine Sende /Empfangs Umschaltung mache.

Ajax habe ich getestet und ist ~50ms langsamer aber die callbacks kommen viel gleichmäßiger nicht so wirr wie beim Websocket.
 
Nee leider geht das auch nicht, da selbst wenn ich einen 3000byte großen Puffer zum esp sende und exakt diesen wider zurücksende dauert es zu lange. im Browser läuft der puffer über.
wenn ein puffer im Browser voll läuft, kann das doch fast nicht am esp liegen. der browser sendet die daten doch nur zum esp und gut. klar, tcp erwartet eine rückmeldung, darauf wartet allerdings das 2. send nicht. gut, irgendwann ist auch der puffer des ip-stacks voll. dann sollte aber nicht dein puffer überlaufen, sondern das send des websockets eine fehlermeldung bringen.
um das mal auszutesten kannst du mal versuchen die puffer des systems zu vergrößern, dann sollte es länger laufen.
unter windows ist das der registry eintrag [HKEY_LOCAL_MACHINE \SYSTEM \CurrentControlSet \Services \Afd \Parameters]
nicht vergessen das nach dem test wieder in den originalzustand zu bringen

- - - Aktualisiert - - -

jetzt hab ich mir mal deinen code angesehen, du machst das transmit() in abhängigkeit von handleOnmessage
das ist nur zum testen? warum rufst du transmit() nicht immer auf, wenn was zu senden da ist?
 
tsseh schrieb:
jetzt hab ich mir mal deinen code angesehen, du machst das transmit() in abhängigkeit von handleOnmessage
das ist nur zum testen? warum rufst du transmit() nicht immer auf, wenn was zu senden da ist?
Nein, da ist nicht nur zum testen. So war der Plan. Wie gesagt ich hätte gerne eine Voll-Duplex Lösung und bin davon ausgegangen das das Senden/Empfangen so schnell geht, das es zu keine nennenswerten delay kommt. Ja, wie du seihst ~100ms delay pro onmessage.

Sende ich immer wenn Daten da sind, bräuchte ich eine Sende-Empfangs Umschaltung. Sprich einen Button den man drückt wenn wenn man was senden Möchte. Der ESP muss halt drauf reagieren.


So mache ich's nun auch, weil ich bin mit meinem Latein am ende.
Festgestellt habe ich bis jetzt nur, das ab 32000byte/sec es zu 1sec delay kommt zwischen Sound Input und der Ausgabe.

Und beim avr beeinflusst der ADC die SPI Übertragung, da bin ich gerade dran am Eruieren warum das so ist.

- - - Aktualisiert - - -

xorg1990 schrieb:
Und beim avr beeinflusst der ADC die SPI Übertragung, da bin ich gerade dran am Eruieren warum das so ist.
Ich komme nicht dahinter, immer wenn ich eine adc Wandlung mache ADCSRA |= (1 << ADSC); kommt am USIDR müll raus.

Sprich ich sende vom esp zum avr nur Nullen, ergo sollte die LED aus sein. Das haut auch hin, nur immer wenn ich eine ADC Wandlung vornehme Free Running oder Anders blinkert die LED Unkontrolliert, es knattert und knarzt wie damals beim ESP.

Code:
#define F_CPU 8000000UL


#define bufferSize 128
#define BUFFER_MASK (bufferSize-1)
/*
  Pinmodes
  PB0 MOSI
  PB1 MISO
  PB2 Clock
  PB3 ADC Input
  PB4 PWM Out
*/
static struct adc_FIFO {//ringBuffer als struct für pcm saples
  byte data[bufferSize];
  volatile byte read_ptr; // zeigt auf das Feld mit dem ältesten Inhalt
  volatile byte write_ptr; // zeigt immer auf leeres Feld
} adc_buffer = {{}, 0, 0};

static struct pcm_samples_buffer {//ringBuffer als struct für pcm saples
  byte data[bufferSize];
  volatile byte read_ptr; // zeigt auf das Feld mit dem ältesten Inhalt
  volatile byte write_ptr; // zeigt immer auf leeres Feld
} pcm_buffer = {{}, 0, 0};

void setup() {
    //pinModes
  pinMode(0, INPUT);// initialize the MOSI Port (PIN 0)
  pinMode(1, OUTPUT);// initialize the MISO Port (PIN 1)
  pinMode(2, INPUT);// initialize the SCK Port (PIN 2)
  pinMode(4, OUTPUT);
  pinMode(3, INPUT);
  cli();
  // Enable 64 MHz PLL and use as source for Timer1
  PLLCSR = 1 << PCKE | 1 << PLLE;
  // Set up Timer/Counter1 for PWM output
  TIMSK = 0;                              // Timer interrupts OFF
  TCCR1 = 1 << CS10; //1<<PWM1A | 2<<COM1A0 | 1<<CS10; // PWM A, clear on match, 1:1 prescale
  GTCCR = 1 << PWM1B | 2 << COM1B0;       // PWM B, clear on match
  OCR1B = 128;               // 50% duty at start on pin PB4
  // Set up Timer/Counter0 for 19230Hz interrupt to output samples.
  TCCR0A = 3 << WGM00;                    // Fast PWM sets bits WGM00 and WGM01, which (when combined with WGM02 from TCCR0B below) enables Fast PWM mode
  TCCR0B = 1 << WGM02 | 2 << CS00;        // 1/8 prescale
  TIMSK = 1 << OCIE0A;                    // Enable compare match
  OCR0A = 51;                            // 19kHz Fs

    //ADC settings 8bit value
  ADMUX =   3 | //channel 3
            (1 << ADLAR) |     // left shift result
            (0 << REFS2) |     // Sets ref. voltage to internal 1.1V, bit 2
            (1 << REFS1) |     // Sets ref. voltage to internal 1.1V, bit 1
            (0 << REFS0) ;     // Sets ref. voltage to internal 1.1V, bit 0

  ADCSRA =
    (1 << ADEN)  |     // Enable ADC at 19230 Hz Samplerate
    (1 << ADPS2) |     // set prescaler to 32, bit 2
    (0 << ADPS1) |     // set prescaler to 32, bit 1
    (1 << ADPS0) |      // set prescaler to 32, bit 0
    (1 << ADIE); //enabel adc isr
    
//SPI settings 
  USICR = (1 << USIWM0) // SPI mode; Uses DO, DI, and USCK pins.
          | (1 << USIOIE) // Enable interrupt
          | (1 << USICS1) // Clock is external postivie flanke
          | (0 << USICS0); // SPI Mode 0


  sei();  // enable interrupts
  ADCSRA |= (1 << ADSC);            // Start the first conversion
  while (ADCSRA & (1 << ADSC) )         // auf Abschluss der Konvertierung warten
  {
  }
  /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
     Wandlung nicht übernommen. */
  (void) ADCH;
}


ISR(ADC_vect) { // interuppt each 38kHz
  byte adcValue = ADCH;
  byte next = ((adc_buffer.write_ptr + 1) & BUFFER_MASK);
  if (adc_buffer.read_ptr != next) {
    adc_buffer.data[adc_buffer.write_ptr] = adcValue;
    //buffer.data[buffer.write_ptr & BUFFER_MASK] = byte;
    adc_buffer.write_ptr = next;
  }
  ADCSRA |= (1 << ADSC);        // Start the next conversion
}


// Sample interrupt 19khz
ISR(TIMER0_COMPA_vect) {
  if (pcm_buffer.read_ptr != pcm_buffer.write_ptr) {
    byte sample  =  pcm_buffer.data[pcm_buffer.read_ptr];
    pcm_buffer.data[pcm_buffer.read_ptr] = 0;
    OCR1B = sample;
    pcm_buffer.read_ptr = (pcm_buffer.read_ptr + 1) & BUFFER_MASK;
  }
}

ISR(USI_OVF_vect) {
  byte incommingByte = 0;
  // Wait for complete byte to arrive
  while ((USISR & (1 << USIOIF)) == 0) {
  }
  // Clear counter overflow flag so next byte can begin arriving
  // While we're processing this one
  USISR = (1 << USIOIF);
  incommingByte = USIDR;
  byte next = ((pcm_buffer.write_ptr + 1) & BUFFER_MASK);
  if (pcm_buffer.read_ptr != next) {
    pcm_buffer.data[pcm_buffer.write_ptr] = incommingByte;
    pcm_buffer.write_ptr = next;
  } else {
    pcm_buffer.data[pcm_buffer.write_ptr] = 0;
  }
  if (adc_buffer.read_ptr !=   adc_buffer.write_ptr) {
    byte adcValue =  adc_buffer.data[adc_buffer.read_ptr];
    adc_buffer.data[adc_buffer.read_ptr] = 0;
    USIDR = adcValue; // Put data in USI data register.
    adc_buffer.read_ptr = (adc_buffer.read_ptr + 1) & BUFFER_MASK;
  } else {
    USIDR = 0;// Put data in USI data register.
  }
}

void loop() {
}

Was auf jeden Fall funzt ist die Übertagung vom Browser zum ESP und dann zum avr, der daraus PWM Audio macht. Nur um da erstmal ein Strich drunter zu machen.
 
Zuletzt bearbeitet:
Nein, da ist nicht nur zum testen. So war der Plan. Wie gesagt ich hätte gerne eine Voll-Duplex Lösung und bin davon ausgegangen das das Senden/Empfangen so schnell geht, das es zu keine nennenswerten delay kommt.
und warum musst du dann warten mit senden, bis du wieder was empfangen hast?

Sende ich immer wenn Daten da sind, bräuchte ich eine Sende-Empfangs Umschaltung. Sprich einen Button den man drückt wenn wenn man was senden Möchte.
nee, jedenfalls hat das nichts mit senden wenn daten da sind zu tun, ob du das generell brauchst, keine ahnung

Der ESP muss halt drauf reagieren.
dafür gibt es ja die events

Und beim avr beeinflusst der ADC die SPI Übertragung, da bin ich gerade dran am Eruieren warum das so ist.
der interrupt des ADC wird den des SPI unterbrechen/verzögern

- - - Aktualisiert - - -

// Enable ADC at 19230 Hz Samplerate
wie kommst du auf 19230 Hz?
ISR(ADC_vect) { // interuppt each 38kHz
jetzt 38kHz? was hast du für eine cpu frequenz? 16MHz? dann wäre deine adc clock mit 500kHz aber zu schnell

while ((USISR & (1 << USIOIF)) == 0) {
}
das sollte nicht notwendig sein

Ich komme nicht dahinter, immer wenn ich eine adc Wandlung mache ADCSRA |= (1 << ADSC); kommt am USIDR müll raus.
das sehe ich so auch erst mal nicht. die isr's "sehen" nicht nach langer laufzeit "aus". die tacktgeber der isr's sind auch unabhängig.
1) müsste man mal die echte laufzeit der jeweiligen isr's wissen. also entweder den asm-code ansehen und die zyklen ausrechnen (hier jeweils am befehl ganz am ende http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_instruction_list.html) oder am anfang und ende der isr jeweils einen gpio toggeln und dann messen
2) müsste man mal die prioritäten der isr's raussuchen um auszuschließen das einer verhungert weil die beiden höherprioren sich immer abwechseln (dazu müsste aber die laufzeit aus 1 auch schon zu groß sein)
am besten wäre du könntest in jeder isr einen anderen gpio toggeln und diesen mit 3 kanälen aufzeichnen.
 
Zuletzt bearbeitet:
tsseh schrieb:
und warum musst du dann warten mit senden, bis du wieder was empfangen hast?
Wo warte ich denn?? Also wo warte ich absichtlich?? Woher die ~100ms delay kommen ist ja die große Frage.


tsseh schrieb:
der interrupt des ADC wird den des SPI unterbrechen/verzögern
Möglich.

tsseh schrieb:
wie kommst du auf 19230 Hz?
8Mhz CPU Clock
ADC Vorteiler 32

8 000 000/32=250000Hz
250000/13=19230Hz SampleRate.

Durch 13 deswegen, weil eine Wandlung 13 Takte braucht.

tsseh schrieb:
jetzt 38kHz? was hast du für eine cpu frequenz? 16MHz? dann wäre deine adc clock mit 500kHz aber zu schnell
Ignoriere das! Der Kommentar stammt noch aus versuch 1.

tsseh schrieb:
das sollte nicht notwendig sein
Da wäre ich mir nicht so sicher. Wenn man das bei einer ADC ISR macht hast du da eine Endlosschleife, weil die Wandlung bereits abgeschlossen ist wenn die ISR gefeuert wird. Bei der usi ISR warte ich bis ein komplettes Byte übertragen wurde, da SPI immer nur bit's überträgt.

Man kann es ja mal weglassen.

tsseh schrieb:
das sehe ich so auch erst mal nicht. die isr's "sehen" nicht nach langer laufzeit "aus". die tacktgeber der isr's sind auch unabhängig.
1) müsste man mal die echte laufzeit der jeweiligen isr's wissen. also entweder den asm-code ansehen und die zyklen ausrechnen (hier jeweils am befehl ganz am ende Atmel AVR 8-bit and 32-bit Microcontrollers) oder am anfang und ende der isr jeweils einen gpio toggeln und dann messen
2) müsste man mal die prioritäten der isr's raussuchen um auszuschließen das einer verhungert weil die beiden höherprioren sich immer abwechseln (dazu müsste aber die laufzeit aus 1 auch schon zu groß sein)
am besten wäre du könntest in jeder isr einen anderen gpio toggeln und diesen mit 3 kanälen aufzeichnen.
Glaube nicht das an den ISR's liegt.
Den USI_OVF_vect feuert der ESP, da der Master ist.

Und selbst wenn ich in der Haupt schleife eine Einzelmessung mache, also ISR(ADC_vect) komplett weg lasse habe ich immer noch das Problem.

- - - Aktualisiert - - -

ok, das while ((USISR & (1 << USIOIF)) == 0) { kann tatsächlich weggelassen werden.

aber die LED an PB4 hat dennoch ein Eigenleben, Problem nicht behoben.

Die ISR'S von adc und vom usi habe ich mal ausgeschalten und dafür das in die loop geschrieben:

Code:
void loop() {
   ADCSRA |= (1 << ADSC);        // Start the next conversion
    while (ADCSRA & (1 << ADSC) )         // auf Abschluss der Konvertierung warten
  {
  }
  byte adcValue = ADCH;
  byte next_a = ((adc_buffer.write_ptr + 1) & BUFFER_MASK);
  if (adc_buffer.read_ptr != next_a) {
    adc_buffer.data[adc_buffer.write_ptr] = adcValue;
    //buffer.data[buffer.write_ptr & BUFFER_MASK] = byte;
    adc_buffer.write_ptr = next_a;
  }
  
   byte incommingByte = 0;
  // Wait for complete byte to arrive
  while ((USISR & (1 << USIOIF)) == 0) {}
  // Clear counter overflow flag so next byte can begin arriving
  // While we're processing this one
  USISR = (1 << USIOIF);
  incommingByte = USIDR;
  byte next = ((pcm_buffer.write_ptr + 1) & BUFFER_MASK);
  if (pcm_buffer.read_ptr != next) {
    pcm_buffer.data[pcm_buffer.write_ptr] = incommingByte;
    pcm_buffer.write_ptr = next;
  } else {
    pcm_buffer.data[pcm_buffer.write_ptr] = 0;
  }
  if (adc_buffer.read_ptr !=   adc_buffer.write_ptr) {
    byte adcValue =  adc_buffer.data[adc_buffer.read_ptr];
    adc_buffer.data[adc_buffer.read_ptr] = 0;
    USIDR = adcValue; // Put data in USI data register.
    adc_buffer.read_ptr = (adc_buffer.read_ptr + 1) & BUFFER_MASK;
  } else {
    USIDR = 0;// Put data in USI data register.
  }
}
Keine Änderung.

Nochmal zum Verständnis, die LED hängt an PB4, und der Analog Pin ist PB3. Die SPI Pins sind die wie im Datenblatt.
 
Wo warte ich denn?? Also wo warte ich absichtlich??
du wartest mit dem senden, bis wieder daten angekommen sind, obwohl du sie schon losschicken könntest, wenn daten in deinem puffer sind


Da wäre ich mir nicht so sicher. Wenn man das bei einer ADC ISR macht hast du da eine Endlosschleife, weil die Wandlung bereits abgeschlossen ist wenn die ISR gefeuert wird.
??? was hat das mit dem adc zu tun?

Bei der usi ISR warte ich bis ein komplettes Byte übertragen wurde, da SPI immer nur bit's überträgt.
genau dann kommt ja der interrupt, bei counter overflow, dann darauf zu warten, dass das counter overflow bit gesetzt ist macht keinen sinn.
selbst wenn du den interrupt so konfiguriert hättest, das er nicht nur bei counter overflow kommt, wäre das warten auf counter overflow in der isr noch schlimmer

Den USI_OVF_vect feuert der ESP, da der Master ist.
naja, sagen wir der master ist taktschläger

Und selbst wenn ich in der Haupt schleife eine Einzelmessung mache, also ISR(ADC_vect) komplett weg lasse habe ich immer noch das Problem.
ok, dann ist das ein hardwareproblem. vielleicht nutzt der adc den timer1. wie kommst du eigentlich darauf, das die spi-übertragung betroffen ist?

ok, das while ((USISR & (1 << USIOIF)) == 0) { kann tatsächlich weggelassen werden.

aber die LED an PB4 hat dennoch ein Eigenleben, Problem nicht behoben.
ja, das waren auch nur die sachen die mir generell komisch vorkamen

Die ISR'S von adc und vom usi habe ich mal ausgeschalten und dafür das in die loop geschrieben:
... sehe ich mir später noch an

- - - Aktualisiert - - -

bei deinen timern stimmt mMn was nicht.
Code:
TCCR1 = 1 << CS10; //1<<PWM1A | 2<<COM1A0 | 1<<CS10; // PWM A, clear on match, 1:1 prescale
...
TCCR0A = 3 << WGM00;                    // Fast PWM sets bits WGM00 and WGM01, which (when combined with WGM02 from TCCR0B below) enables Fast PWM mode
TCCR0B = 1 << WGM02 | 2 << CS00;        // 1/8 prescale
timer 0 ist doch der 8 bit timer und timer 1 der 16 bit
damit sollte es TCCR1A und B geben und TCCR0????
 
tsseh schrieb:
du wartest mit dem senden, bis wieder daten angekommen sind, obwohl du sie schon losschicken könntest, wenn daten in deinem puffer sind
Naja, weil die Wlan Verbindung nicht Voll-Duplex fähig ist. Da geht immer nur eins von beiden.

tsseh schrieb:
?? was hat das mit dem adc zu tun?
War nur so erläutert.

tsseh schrieb:
genau dann kommt ja der interrupt, bei counter overflow, dann darauf zu warten, dass das counter overflow bit gesetzt ist macht keinen sinn.
selbst wenn du den interrupt so konfiguriert hättest, das er nicht nur bei counter overflow kommt, wäre das warten auf counter overflow in der isr noch schlimmer
ok.
tsseh schrieb:
wie kommst du eigentlich darauf, das die spi-übertragung betroffen ist?
Ganz einfach, wenn ich statt incommingByte = USIDR; incommingByte = 0 schreib habe ich keine Probleme.

tsseh schrieb:
timer 0 ist doch der 8 bit timer und timer 1 der 16 bit
damit sollte es TCCR1A und B geben und TCCR0????
Doch das haut hin, der Attiny85 hat gar kein 16 bit Timer.
http://www.atmel.com/images/atmel-2...ller-attiny25-attiny45-attiny85_datasheet.pdf

Wie gesagt, wenn der adc nix macht funzt alles.

Habe ich schon erwähnt, dass wen ich den esp abschalte oder die Kabels abziehe für die SPI Verbindung auch alles seine Wege geht.
 
Naja, weil die Wlan Verbindung nicht Voll-Duplex fähig ist. Da geht immer nur eins von beiden.
das ist aber nichts was DU beachten musst. du übergibst deine daten an den ip-stack, der ist für den rest verantwortlich


Ganz einfach, wenn ich statt incommingByte = USIDR; incommingByte = 0 schreib habe ich keine Probleme.
ok, dann würde ich als erstes testen ob tatsächlich werte != 0 ankommen, über ne LED die du anschaltest, wenn der 1. wert != 0 erkannt wird. das wird mit hoher wahrscheinlichkeit passieren.
dann würde ich testen, ob es am avr oder esp liegt. einfach einen 2. avr verbinden der nichts anderes macht als 0 zu schicken.
wenn dann das problem immer noch auftritt, hast du ein problem.

Doch das haut hin, der Attiny85 hat gar kein 16 bit Timer.
ok

Habe ich schon erwähnt, dass wen ich den esp abschalte oder die Kabels abziehe für die SPI Verbindung auch alles seine Wege geht.
naja, dann kommen ja auch keine werte über spi und die 0 die du einmal ausgegeben hast liegt weiter an dem gpio an
 
tsseh schrieb:
das ist aber nichts was DU beachten musst. du übergibst deine daten an den ip-stack, der ist für den rest verantwortlich
Wenn es doch nur so einfach wäre. Mache ich's wie von dir beschrieben, dann endet das mit einem Watchdog reset.


tsseh schrieb:
dann würde ich testen, ob es am avr oder esp liegt.
Jep, denke auch das der ESP daran schuld ist.
 
Wenn es doch nur so einfach wäre. Mache ich's wie von dir beschrieben, dann endet das mit einem Watchdog reset.
das zeigt ja, dass der esp soviel daten nicht verarbeiten kann die du sendest.
dann geht es zwar mit warten, aber die 100ms werden eben benötigt um die daten die der esp empfängt zu verarbeiten
 
tsseh schrieb:
das zeigt ja, dass der esp soviel daten nicht verarbeiten kann die du sendest.
dann geht es zwar mit warten, aber die 100ms werden eben benötigt um die daten die der esp empfängt zu verarbeiten
Dann ist der esp aber echt lahm. Es macht auch kein Unterschied den esp mit 160 oder 80Mhz laufe zu lassen Die OFDM Modulation scheint separat in Hardware gegossen zu sein.

Habe auch nochmal ausprobiert, wenn ich sende und empfange gleichzeitig, dann kommt gar kein onmessege event. Entweder kommt der Watchdog oder die WS Verbindung wird einfach so geschlossen.

Beim avr habe ich das Problem gefunden es lag an dieser Zeile.
USISR = (1 << USIOIF);
Das ganz am ende der isr und schon geht's .... naja fast, diesmal ging der PWM output nicht nur geknarze und gerausche.

Hab die USI ISR koplett deaktivert und alles in die While gepackt:
Code:
#define F_CPU 8000000UL
#include "pins_arduino.h"


#define bufferSize 128
#define BUFFER_MASK (bufferSize-1)
/*
  Pinmodes
  PB0 MOSI
  PB1 MISO
  PB2 Clock
  PB3 ADC Input
  PB4 PWM Out
*/
static struct adc_FIFO {//ringBuffer als struct für pcm saples
  byte data[bufferSize];
  volatile byte read_ptr; // zeigt auf das Feld mit dem ältesten Inhalt
  volatile byte write_ptr; // zeigt immer auf leeres Feld
} adc_buffer = {{}, 0, 0};

static struct pcm_samples_buffer {//ringBuffer als struct für pcm saples
  byte data[bufferSize];
  volatile byte read_ptr; // zeigt auf das Feld mit dem ältesten Inhalt
  volatile byte write_ptr; // zeigt immer auf leeres Feld
} pcm_buffer = {{}, 0, 0};

void setup() {
  cli();
  // Enable 64 MHz PLL and use as source for Timer1
  PLLCSR = 1 << PCKE | 1 << PLLE;
  // Set up Timer/Counter1 for PWM output
  TIMSK = 0;                              // Timer interrupts OFF
  TCCR1 = 1 << CS10; //1<<PWM1A | 2<<COM1A0 | 1<<CS10; // PWM A, clear on match, 1:1 prescale
  GTCCR = 1 << PWM1B | 2 << COM1B0;       // PWM B, clear on match
  OCR1B = 128;               // 50% duty at start on pin PB4
  // Set up Timer/Counter0 for 44.1kHz interrupt to output samples.
  TCCR0A = 3 << WGM00;                    // Fast PWM sets bits WGM00 and WGM01, which (when combined with WGM02 from TCCR0B below) enables Fast PWM mode
  TCCR0B = 1 << WGM02 | 2 << CS00;        // 1/8 prescale
  TIMSK = 1 << OCIE0A;                    // Enable compare match
  OCR0A = 51;                            // 19kHz Fs
  //pinModes
  pinMode(0, INPUT);// initialize the MOSI Port (PIN 0)
  pinMode(1, OUTPUT);// initialize the MISO Port (PIN 1)
  pinMode(2, INPUT);// initialize the SCK Port (PIN 2)
  pinMode(4, OUTPUT);
  pinMode(3, INPUT);

  USICR = (1 << USIWM0) // SPI mode; Uses DO, DI, and USCK pins.
          //| (1 << USIOIE) // Enable interrupt
          | (1 << USICS1) // Clock is external postivie flanke
          | (0 << USICS0); // SPI Mode 0

  //ADC settings 8bit value
  ADMUX =   3 | //channel 3
            (1 << ADLAR) |     // left shift result
            (0 << REFS2) |     // Sets ref. voltage to internal 1.1V, bit 2
            (1 << REFS1) |     // Sets ref. voltage to internal 1.1V, bit 1
            (0 << REFS0) ;     // Sets ref. voltage to internal 1.1V, bit 0

  ADCSRA =
    (1 << ADEN)  |     // Enable ADC at 19230 Hz Samplerate
    (1 << ADSC)    | // start conversion
    (1 << ADATE)   | // free running
    (1 << ADPS2) |     // set prescaler to 8, bit 2
    (0 << ADPS1) |     // set prescaler to 8, bit 1
    (1 << ADPS0) |      // set prescaler to 8, bit 0
    (1 << ADIE); //enabel adc isr
  sei();  // enable interrupts
  /*
  ADCSRA |= (1 << ADSC);            // Start the first conversion
  while (ADCSRA & (1 << ADSC) )         // auf Abschluss der Konvertierung warten
  {
  }
  */
  /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
     Wandlung nicht übernommen. */
  (void) ADCH;
}


ISR(ADC_vect) { // interuppt each 38kHz
  byte adcValue = ADCH;
  byte next = ((adc_buffer.write_ptr + 1) & BUFFER_MASK);
  if (adc_buffer.read_ptr != next) {
    adc_buffer.data[adc_buffer.write_ptr] = adcValue;
    //buffer.data[buffer.write_ptr & BUFFER_MASK] = byte;
    adc_buffer.write_ptr = next;
  }
  //ADCSRA |= (1 << ADSC);        // Start the next conversion
}


// Sample interrupt 38khz
ISR(TIMER0_COMPA_vect) {
  if (pcm_buffer.read_ptr != pcm_buffer.write_ptr) {
    byte sample  =  pcm_buffer.data[pcm_buffer.read_ptr];
    pcm_buffer.data[pcm_buffer.read_ptr] = 0;
    OCR1B = sample;
    pcm_buffer.read_ptr = (pcm_buffer.read_ptr + 1) & BUFFER_MASK;
  }
}

/*
ISR(USI_OVF_vect) {
  byte incommingByte = 0;
  // Wait for complete byte to arrive
  //while ((USISR & (1 << USIOIF)) == 0) {
 // }
  incommingByte = USIDR;
  byte next = ((pcm_buffer.write_ptr + 1) & BUFFER_MASK);
  if (pcm_buffer.read_ptr != next) {
    pcm_buffer.data[pcm_buffer.write_ptr] = incommingByte;
    pcm_buffer.write_ptr = next;
  } else {
    pcm_buffer.data[pcm_buffer.write_ptr] = 0;
  }
    
  if (adc_buffer.read_ptr !=   adc_buffer.write_ptr) {
    byte adcValue =  adc_buffer.data[adc_buffer.read_ptr];
    adc_buffer.data[adc_buffer.read_ptr] = 0;
    USIDR = adcValue; // Put data in USI data register.
    adc_buffer.read_ptr = (adc_buffer.read_ptr + 1) & BUFFER_MASK;
  } else {
    USIDR = 0;// Put data in USI data register.
  }

  // Clear counter overflow flag so next byte can begin arriving
  // While we're processing this one
  USISR = (1 << USIOIF);
  
}
*/

void loop() {
  byte incommingByte = 0;
  // Wait for complete byte to arrive
  while ((USISR & (1 << USIOIF)) == 0) {}
  
  incommingByte = USIDR;
  byte next = ((pcm_buffer.write_ptr + 1) & BUFFER_MASK);
  if (pcm_buffer.read_ptr != next) {
    pcm_buffer.data[pcm_buffer.write_ptr] = incommingByte;
    pcm_buffer.write_ptr = next;
  } else {
    pcm_buffer.data[pcm_buffer.write_ptr] = 0;
  }
    
  if (adc_buffer.read_ptr !=   adc_buffer.write_ptr) {
    byte adcValue =  adc_buffer.data[adc_buffer.read_ptr];
    adc_buffer.data[adc_buffer.read_ptr] = 0;
    USIDR = adcValue; // Put data in USI data register.
    adc_buffer.read_ptr = (adc_buffer.read_ptr + 1) & BUFFER_MASK;
  } else {
    USIDR = 0;// Put data in USI data register.
  }

  // Clear counter overflow flag so next byte can begin arriving
  // While we're processing this one
  USISR = (1 << USIOIF);
  
}
Funzt.:icon7:

Was ich noch nicht weiß ober der adc auch funktioniert. Muss erst mal ein Licht Empfänger basteln.

Auch herausgefunden habe ich, das ich diese isr gar nicht benötige und den dazugehörigen Puffer auch nicht :
Code:
// Sample interrupt 38khz
ISR(TIMER0_COMPA_vect) {
  if (pcm_buffer.read_ptr != pcm_buffer.write_ptr) {
    byte sample  =  pcm_buffer.data[pcm_buffer.read_ptr];
    pcm_buffer.data[pcm_buffer.read_ptr] = 0;
    OCR1B = sample;
    pcm_buffer.read_ptr = (pcm_buffer.read_ptr + 1) & BUFFER_MASK;
  }
}

Ich kann direkt OCR1B = USIDR schreiben.

Aber, Frage:
Was hältst du von der Pufferung, ist es besser eine zu haben oder kann ich die auch komplett weglassen?
Dann kann man den Attiny45 satt 85 nehmen ist zwar Pfennig kram aber immerhin.
 
Habe auch nochmal ausprobiert, wenn ich sende und empfange gleichzeitig, dann kommt gar kein onmessege event. Entweder kommt der Watchdog oder die WS Verbindung wird einfach so geschlossen.
dann hast du vermutlich noch ein anderes problem

Beim avr habe ich das Problem gefunden es lag an dieser Zeile.
USISR = (1 << USIOIF);
ja, das ist falsch, auch am ende. das statusregister zu schreiben ist keine gute idee

Hab die USI ISR koplett deaktivert und alles in die While gepackt:
keine gute idee, wenn es einen int gibt, sollte man den auch nutzen

Auch herausgefunden habe ich, das ich diese isr gar nicht benötige und den dazugehörigen Puffer auch nicht :
der isr sorgt doch aber für einen 38khz takt, ohne taktest du ja immer wenn ein wert über spi angekommen ist.
wenn das mit fester taktrate passiert und die frequenz passt, kannst du darauf verzichten
 
tsseh schrieb:
dann hast du vermutlich noch ein anderes problem
Dann weiß ich aber auch nicht an was es liegen soll. Es gäbe noch die Möglichkeit der Datenkompression aber ob der ESP das schafft ? Ich würde mich da auf adpcm beschränken. mp3, vorbis etc, ist alles zu kompliziert.

tsseh schrieb:
ja, das ist falsch, auch am ende. das statusregister zu schreiben ist keine gute idee
Wie jetzt ich soll die Zeile komplett weglassen??

tsseh schrieb:
wenn es einen int gibt, sollte man den auch nutzen
was meinst du mit int?? Integer? Erläutere das mal genauer?

tsseh schrieb:
wenn das mit fester Taktrate passiert und die Frequenz passt, kannst du darauf verzichten
Ja, das ist synchron. Manchmal ist es aber besser eine kleine Puffer zu haben, im falle die SPI Übertragung hat mal kleinere Aussetzer.
 
Dann weiß ich aber auch nicht an was es liegen soll.
irgendwas musst du ja machen auf dem esp was die zeit frisst. wenn du daten zum esp sendest, empfängt dieser die. das was du dann (mit den daten?) machst, dauert so lange, daß du nicht mal mehr zum antworten kommst ehe die nächsten daten eintreffen

Wie jetzt ich soll die Zeile komplett weglassen??
ja, wozu soll die gut sein? das flag setzt der esp wenn ein byte angekommen ist, nicht du. maximal musst du sowas zurücksetzten

was meinst du mit int?? Integer? Erläutere das mal genauer?
interrupt

Ja, das ist synchron. Manchmal ist es aber besser eine kleine Puffer zu haben, im falle die SPI Übertragung hat mal kleinere Aussetzer.
entweder ist es synchron oder hat aussetzer. die frage ist kannst du mit den aussetzern leben und musst du das überhaupt.
ohne puffer spaarst du diesen,m waren aber auch nur 128 byte, außerden sparrst du laufzeit. beides sollte eigentlich ausreichend zur verfügung stehen, also müsstest du nicht damit leben.
 
tsseh schrieb:
irgendwas musst du ja machen auf dem esp was die zeit frisst.
Habe alle möglichen Sachen ausprobiert an mir liegt es nicht. Selbst wenn der esp nur eine Puffer empfängt und exakt diesen wieder sendet wird es nicht besser. Entweder liegt es an der websocket klasse oder an der Wlan Modulation.
Wenn du mal Zeit hast kannst du dir mal diese Playlist ansehen: https://www.youtube.com/watch?v=VhgkCoVYhBI&list=PLvUvEbh7a8u_Wqtn7VpVhh_eZALqmLCQh

Dan hast du einen Überblick wie aufwendig das zu Programmieren ist.

tsseh schrieb:
entweder ist es synchron oder hat aussetzer. die frage ist kannst du mit den aussetzern leben und musst du das überhaupt.
Ausprobieren.

tsseh schrieb:
dann ist am ende nicht falsch, jede andere stelle aber auch nicht, da spi kein clock stretching unterstützt
Also mit der usi isr wird es überhaupt nix, da dreht die LED durch wenn eine ADC Wandlung im Gange ist. Bzw die SPI Übertagung produziert Unsinn . Es klappt nur mit der von mir zuletzt geposteten Lösung in der while. Stange:confused:
 
ich hab das jetzt mal selbst ausprobiert websocket zum esp.
das sind meine zeiten:ws.png
ich schicke immer 100 byte zum esp und der sendet sie zurück. die zeiten sind immer von vor dem senden bis zum empfang der daten die zurückgeschickt wurden.
100 byte habe ich genommen, weil das websocket-protokoll ab 126 byte payload etwas komplizierter wird und die arbeit wollte ich mir spaaren, aber das sollte als anhaltspunkt schon mal reichen.
 
Sry das ich jetzt erst antworte, brauchte mal 'ne Pause.

Die Zeiten sehn gut aus.

tsseh schrieb:
websocket-protokoll ab 126 byte payload etwas komplizierter wird
Warum?


Bei avr habe ich noch festgestellt, dass die Adc Wandlung nur gut funktioniert wenn man ein Prescalar von 16 wählt. Ist man schneller oder langsamer versteht man keine Sprache mehr.

Problem, ein Prescalar von 16 entspricht ~38khz Sample rate, das ist zu viel für den ESP. Ich lasse die SPI Übertragung einfach um die Hälfte langsamer laufen, dann wird zwar jeder 2te adc Wert übersprungen... aber sei's drum, geht.
 
weil die nutzdatenlängen bei 126 im nächsten word steht und bei 127 im nächsten dword
https://tools.ietf.org/html/rfc6455#section-5.2

Problem, ein Prescalar von 16 entspricht ~38khz Sample rate, das ist zu viel für den ESP. Ich lasse die SPI Übertragung einfach um die Hälfte langsamer laufen, dann wird zwar jeder 2te adc Wert übersprungen... aber sei's drum, geht.
das ist doch aber kein problem. deine sample rate wird doch sowieso durch die SPI-taktung bzw. deinen timer(den du glaube ich nicht mehr verwendest) festgelegt. du hattest doch 8khz sample rate. dann musst du einfach in diesem takt diene werte wandeln. das ist doch sogar besser als wenn du dicht an die 38khz des adc rankommen würdest.
 
tsseh schrieb:
weil die nutzdatenlängen bei 126 im nächsten word steht und bei 127 im nächsten dword
Und das soll sich auf die Übertragungsgeschwindigkeit auswirken?
tsseh schrieb:
dann musst du einfach in diesem takt diene werte wandeln.
Naja so einfach ist es dann doch nicht. Ich hatte mir ein attiny gebastelt der einen ADC Wert direkt wider als PWM ausgibt. Nur um erst mal grundsätzlich zu klären ob sich der Attiny überhaupt als Soundkarten(besser ADC) Ersatz eignet, für Audio.

Und dabei bin ich dahinter gekommen das die Audioqualität dann am besten ist, wenn der Prescaler auf 16 steht einspricht ~38Khz, wird die Wandlung schneller rauscht es, ist es langsamer sind die Frequenzen verschoben . Ist der Prescaler auf 128(das langsamste) geht gar nix los.


Habe man eine frage zum Timer auf dem ESP. Timer0 und Timer1 sind Hardware Timer?

Wie bewege ich Timer 1 dazu alle 51microsec einen Interrupt zu feuern?

Timer 0 geht so.
timer0_write(ESP.getCycleCount() + interval_us * 80); // 160 when running at 160mhz
 
Zurück
Oben