Selbstbau CUN (MapleCUN)

Begonnen von Telekatz, 09 November 2016, 20:29:52

Vorheriges Thema - Nächstes Thema

vbs

#1410
Ich bin jetzt erstmal ein paar Tage weg, aber ich konnte zumindest heute nochmal kurz das signalduino draufpacken. Und: interessanterweise tritt es dort tatsächlich nicht auf.  :o

Also bei signalduino gibt es Probleme die CCs zu finden, wenn ich den Reset-Button am Maple drücke. Dann werden im Prinzip nie beide CCs gefunden. Aber, wenn ich USB-Kabel ziehe und wieder reinstecke, dann wurden immer bei CCs gefunden. Also ich würde definitiv sagen, dass die FW hier einen Unterschied macht.

Könnte ja tatsächlich so sein, wie mein Kollege vermutete, dass die CCs nicht sauber initialisiert/resettet werden bei der aculfw-FW?

Ich hab mal einen Blick ins Datenblatt von dem CC1101 geworfen und da werden zwei Arten beschrieben, den CC beim Starten zu resetten: einen automatischen Reset, bei dem aber dann gewährleistet werden muss, dass die Spannung innerhalb von 5 ms 1,8 V erreicht.
Gibt jedoch auch einen manuellen Reset. Falls sich die FW auf den automatischen Reset verlässt, könnte es ja auch sein, dass das auch mit der Spannungsversorgung zusammenhängt, die das evtl. in meinem Fall ohne separates Netzteil nicht hergibt?

Weiß jemand, ob acul bzw. signalduino einen händischen Reset machen oder "nur" den automatischen nutzen?

vbs

Hm, also die cul-FW und signalduino scheinen beide den manuellen Reset zu machen (wenn ich da die richtigen Stellen gefunden habe):

https://github.com/Ralf9/SIGNALDuino/blob/dev-r422_cc1101/SIGNALduinoAdv/cc1101.h#L689

https://github.com/heliflieger/a-culfw/blob/master/culfw/clib/cc1100.c#L248

Die Implementierung von signalduino scheint aber näher an dem Verfahren zu sein, wie ich es im Datenblatt des CC1101 verstehe. Möglicherweise hat es damit was zu tun. Oder völliger Holzweg...

Telekatz

Der CC1101 wird beim booten des MapleCUL zweimal resettet. Einmal beim Init in cc1100.c und einmal vorher schon während des Autodetects in hw_autodetect.c. Und beim Autodetect fehlt der Toggle des CS Signals. Möglicherweise funktioniert es mit folgender Änderung in hw_autodetect.c:

void hw_autodetect(void) {

  for (CC1101.instance = 0; CC1101.instance < HAS_MULTI_CC; CC1101.instance++) {
    hal_CC_GDO_init(CC1101.instance,INIT_MODE_IN_CS_IN);

    CC1100_DEASSERT;                           // Toggle chip select signal
    my_delay_us(30);
    CC1100_ASSERT;
    my_delay_us(30);
    CC1100_DEASSERT;
    my_delay_us(45);

    ccStrobe( CC1100_SRES );                   // Send SRES command
    my_delay_us(100);
  }


Anbei das .bin mit dieser Änderung zum testen.

vbs

Ahh klasse, vielen Dank, megaspannend! Bin noch unterwegs und werde es erst Sa/So ausprobieren können, aber mache ich dann, sobald ich kann! Danke!

vbs

Sooo, hab es nun testen können: das funktioniert jetzt! Super!
War wohl genau das tatsächlich. Hab viele Male getestet mit dem Ziehen des USB-Kabels und auch einige Male mit der Reset-Taste. Ich hab kein einziges Mal gehabt, dass ein CC nicht gefunden wurde! Also das ist jetzt noch stabiler als mit signalduino  ;)

Dankeschön!!

vbs

Hm, es gab leider einen kleinen Rückschlag: also heute habe ich auch mit der gepatchten Firmware wieder sehr häufig Fälle, wo der 433-CC nicht erkannt wird. Im Prinzip wie ohne den Patch... Sehr seltsam - keine Ahnung, warum.

Was ich zwischendurch gemacht hatte, war, dass ich das Homematic-Modul wieder eingelötet hatte (hatte ich abgelötet, um das als Fehlerquelle auszuschließen). Kann mir aber irgenwie nicht vorstellen, dass das irgendwas mit der Sache zu tun hat. Und ich hatte mir die CUL-FW mit dem gezeigten Code von Telekatz nochmal selbst kompiliert, um es nachzuvollziehen. Aber auch mit der Binary von oben: heute tritt das Problem wieder auf  :(

Aber es gibt auch gute Nachrichten: der Reset der CCs in der FW ist ja nicht so ganz gemäß Datasheet, bin ich der Meinung. Im Datasheet wird davon geredet, dass man auf SO-Pin warten soll. In der FW sind da stattdessen feste Sleeps drin.
Ich hab da mal einfach die Sleep-Zeiten großzügigerweise verdoppelt, um zu gucken, ob das irgendwas ändert. Und sieh da: das hat nun das Problem offenbar wieder gelöst (heute?). Ich hatte damit dann heute wieder viele Button-Resets und viele Dran-/Abstecken des USB-Kabels getestet und damit hatte ich dann wieder keinen Fall mehr, dass ein CC nicht gefunden wurde. Also funktioniert so.
Ich weiß - das hab ich gestern auch schon gesagt. Ich werde das noch etwas beobachten...

Hier der Code mit meinen Timings:
void hw_autodetect(void) {

  for (CC1101.instance = 0; CC1101.instance < HAS_MULTI_CC; CC1101.instance++) {
    hal_CC_GDO_init(CC1101.instance,INIT_MODE_IN_CS_IN);

    CC1100_DEASSERT;                          // Toggle chip select signal
    my_delay_us(60);
    CC1100_ASSERT;
    my_delay_us(60);
    CC1100_DEASSERT;
    my_delay_us(90);

    ccStrobe( CC1100_SRES );                  // Send SRES command
    my_delay_us(200);
  }
Spricht etwas dagegen, die Timings so oder ähnlichen zu ändern? Ich hatte mit der Variante gegenüber der Binary oben von Telekatz bestimmt 5 Mal hin- und her getestet und mit den gelockerten Timings war es dann immer stabil.

Im Idealfall sollte man wohl wirklich auf den SO-Pin warten (wie es ja wohl auch signalduino macht), aber ich hab das im CUL-Code so spontan nicht gefunden, wie man da auf einen Pin warten könnte.

Was haltet ihr davon?

Telekatz

Währe wohl besser, wenn man dann doch den SO Pin überwacht. Zu auslesen des Pins müsste man erst noch eine Funktion ähnlich "hal_CC_Pin_Get(uint8_t cc_num, CC_PIN pin)" bauen.


vbs

Ok, ich guck mir das mal an...

Telekatz

Ich hab die Überwachung des SO Pins in eine Testversion eingebaut.

So Sieht die Abfrage des SO Pins aus:
uint8_t spi_wait_SO_low(SPI_port port) {
  uint32_t pin = 1;
  uint8_t timeout = 0xff;

  while(timeout--) {
    my_delay_us(5);
    switch(port) {
    case SPI_1:
      pin = (GPIOA->IDR) & _BV(6);
      break;
    case SPI_2:
      pin = (GPIOB->IDR) & _BV(14);
      break;
    }
    if(pin == 0)
      return timeout;
  }
  return 0;
}

Und das ist die geänderte Reset-Prozedur:
void hw_autodetect(void) {

  for (CC1101.instance = 0; CC1101.instance < HAS_MULTI_CC; CC1101.instance++) {
    uint32_t timeout;

    hal_CC_GDO_init(CC1101.instance,INIT_MODE_IN_CS_IN);
    CC1100_DEASSERT;                           // Toggle chip select signal
    my_delay_us(30);

    CC1100_ASSERT;
    my_delay_us(10);

    CC1100_DEASSERT;
    my_delay_us(30);

    CC1100_ASSERT;
    timeout = spi_wait_SO_low(CC_SPI);
    TRACE_INFO("SO timeout CC%x: 0x%04x \n\r", CC1101.instance, timeout);

    ccStrobe( CC1100_SRES );                   // Send SRES command
    my_delay_us(1000);
  }

Außerdem habe ich noch festgestellt, dass der Pull-up am SO Eingang nicht aktiviert war.

Anbei das .bin zum Testen. Sofern du die TRACE Debugausgaben mitloggen kannst, wäre es interessant zu wissen, wie weit bei dir der Timeout herunterzählt. Bei mir läuft die Schleife, bis der SO Pin Low ist, nur einmal durch.

vbs

Ich hab dein bin-File eben kurz getestet und das sah erstmal gut aus, danke! Ich will aber nicht wieder zu vorschnell sein und werde noch mehr testen. Und ich versuche noch, die TRACE-Ausgaben zu bekommen.

Müsste man nicht besser auch nach dem SRES auf SO warten anstelle von sleep(1000)?


Ich hatte mich auch schon mal am Code versucht, aber noch nicht vollständig getestet:
typedef enum {
  LL_HIGH = 0,
  LL_LOW
} Logic_Level;

uint8_t hal_CC_Pin_Wait(uint8_t cc_num, CC_PIN pin, Logic_Level level) {
  uint8_t i=7;
  if(cc_num < CCCOUNT) {
    i=8;
    if (CCtransceiver[cc_num].base[pin]) {
      i=0;
      for(; i < 255; ++i) {
        uint8_t state = (CCtransceiver[cc_num].base[pin]->IDR) & _BV(CCtransceiver[cc_num].pin[pin]);
        if (level == LL_HIGH) {
          if (state) {
            break;
          }
        } else { // LL_LOW
          if (!state) {
            break;
          }
        }
        my_delay_us(1);
      }
    }
  }
  return i;
}

uint32_t hal_CC_Pin_Wait_Low(uint8_t cc_num, CC_PIN pin) {
  return hal_CC_Pin_Wait(cc_num, pin, LL_LOW);
}

uint32_t hal_CC_Pin_Wait_High(uint8_t cc_num, CC_PIN pin) {
  return hal_CC_Pin_Wait(cc_num, pin, LL_HIGH);
}

und dann
void hw_autodetect(void) {

  for (CC1101.instance = 0; CC1101.instance < HAS_MULTI_CC; CC1101.instance++) {
    hal_CC_GDO_init(CC1101.instance,INIT_MODE_IN_CS_IN);
/*
    CC1100_DEASSERT;                          // Toggle chip select signal
    my_delay_us(200);
    CC1100_ASSERT;                          // Toggle chip select signal
    my_delay_us(200);
*/

    CC1100_DEASSERT;                          // Toggle chip select signal
    my_delay_us(60);
    CC1100_ASSERT;
    my_delay_us(60);
    CC1100_DEASSERT;
    //my_delay_us(90);

    w1[CC1101.instance] = hal_CC_Pin_Wait_Low(CC1101.instance, CC_Pin_In);

    ccStrobe( CC1100_SRES );                  // Send SRES command

    w2[CC1101.instance] = hal_CC_Pin_Wait_Low(CC1101.instance, CC_Pin_In);

    //my_delay_us(200);
  }

Ich hatte mir auch die Counter in "w1" und "w2" gespeichert, um sehen zu können wie/ob er wirklich wartet. Ich dachte, diese seriellen Ausgaben mit TRACE waren irgendwann aus der FW geflogen? Oder verwechsel ich da was?
Ich hatte zumindest deswegen mir einen Befehl "D" eingebaut, um dann die "w"-Werte auszugeben.

Wäre das wohl prinzipiell so richtig gewesen?

Ich hab nochmal ein Bild gemacht, wie der Reset in einem Logic Analyzer ausgehen hat. Witzigerweise trat der Fehler jedoch nicht mehr auf, sobald der LA angeklemmt war  ;D  mein Kollege sagte, dass sei wohl gar nicht so ungewöhnlich bei sowas...

vbs

Also sorry, aber ich bekomme aus dem Debug-Port echt nix raus. Hab extra nochmal die 1.26.01 gebaut und aufgespielt und da funktioniert es auf Anhieb. Ist der Port echt an in deinem bin? Irgendwas anderes noch zu beachten?

Telekatz

TRACE ist immernoch aktiv. Aber halt nur über SWO. Man braucht halt einen passenden Programmieradapter, z.B J-Link oder Black Magic Probe. Für die Serielle Debug Schnittstelle müsste man erst vorher HAS_UART in der board.h auskommentieren.

Die Funktion "hal_CC_Pin_Get" war doch nicht die richtige Vorlage für die neue Funktion. Man muss ja den MISO Pin abfragen und keinen der drei GDO Pins der CCtransceiver Struct.

vbs

Uh nee, sorry, damit kann ich nicht dienen. Mit HAS_UART kompilieren, bekomme ich hingegen hin. Magst du mal den Code irgendwo pushen?


Hab gesehen, dass du hier eh schon nen PR offen hast?
https://github.com/heliflieger/a-culfw/pull/38

Telekatz

Der PR steht momentan wieder auf Draft bis alles funktioniert. Die aktuellen Änderungen sind jetzt auch auf GitHub.

vbs

Ok, danke, hab ich mal gebaut inkl. Ausgaben. Da kommt dann:
-I- Getting new Started Project --
-I- MapleCUNx4
-I- Compiled: May  7 2025 22:06:15 --
-I- init Flash
-I- init Timer
-I- init EEprom
-I- init Ethernet
WIZCHIP Initialized success.
-I- SO timeout1 CC0: 0x00fe
-I- SO timeout2 CC0: 0x00f9
-I- SO timeout1 CC1: 0x00fe
-I- SO timeout2 CC1: 0x00f9
-I- SO timeout1 CC2: 0x0000
-I- SO timeout2 CC2: 0x0000
-I- SO timeout1 CC3: 0x0000
-I- SO timeout2 CC3: 0x0000
-I- Detected CC0: PN 0x00  VER 0x14
-I- Detected CC1: PN 0x00  VER 0x18
-I- Not detected CC2: PN 0xff  VER 0xff
-I- Not detected CC3: PN 0xff  VER 0xff
-I- Not detected ethernet
-I- Not detected onewire
-I- init USB
-I- init Complete

Hm, also jeder Zähler entspricht 5 us, oder? Vielleicht mit ein paar Zerquetschen obendrauf. Bei 0xf9 kommt man dann aber trotzdem nur auf ca. 35 us. Hätten uns doch zumindest Werte erhofft, die höher als die bisherigen Sleeps sind damit hier irgendwas mal ein bisschen Sinn macht, oder?