- 12V Akku mit 280 Ah bauen         
Seite 3 von 3 ErsteErste 123
Ergebnis 21 bis 23 von 23

Thema: Motorsteuerung über Sensorik

  1. #21
    HaWe
    Gast
    Anzeige

    Powerstation Test
    Zitat Zitat von i_make_it Beitrag anzeigen
    Also
    Wire.endTransmission();
    Beendet die Übertragung und könnte mit den Returncodes 0 bis 4 zum Auswerten des Fehlerstatus benutzt werden.

    Wire.requestFrom(CMPS10Addr , 4);
    Fragt die (in diesem Fall 4) Bytes vom Slave ab. Danach stehen sie im Eingangspuffer.

    Wire.available()
    Gibt an wie viele Bytes im Puffer stehen.

    while (Wire.available() < 4);
    Wartet solange Wire.available() kleiner 4 ist.

    Aber ohne Abbruchbedingung falls der Vergleichswert nie erreicht wird und ohne einen Befehl der die Schleife verzögert.

    Sinnvoll wäre z.B. eine zweite, veroderte Abbruchbedingung und im Körper der Whileschleife ein Hochzählen.
    Wenn dann z.B. nach 1000 Schleifendurchläufen keine 4 Bytes vorhanden sind wird die Schleife durch die zweite Abbruchbedingung trotzdem terminiert und man kännte den Zählerstand auf Erreichen des Maximalwertes auswerten um danach eine Fehlerbehandlung zu starten.

    Will mann es unsauber, Quick & dirty machen, kann man es natürlich nackt hinschreiben, dann kann man es aber auch ganz weglassen und einfach ungeprüft den Puffer auslesen.
    Das erste Wire.endTransmission(); trennt den vorangehenden i2c-write Befehl (um den Slave und seine Register zu adressieren und das Lesen vorzubereiten) von dem darauffolgenden i2c-read.
    Hier auf Fehler zu testen, ist tatsächlich sinnvoll, wenn Verbindungsprobleme bestehen sollten. Dann kann man die Schleife vorzeitig verlassen (Fehlermeldung an Serial.print()!).

    per Wire() zu versuchen, eine bestimmte Anzahl Bytes zu lesen ohne dass sie im Puffer zur Verfügung stehen gibt tatsächlich aber meistens Mist - das wegzulassen ist die schlechteste aller Lösungen: es sollte so stehen bleiben.

    Ein Timeout in die while Schleife einzubauen, ist nicht verkehrt, ist aber bei Arduino Wire() üblicherweise nicht nötig, alle Arduino Beispiel Codes verzichten darauf: wenn 4 Bytes angefordert werden, dann ist damit zu rechnen, dass sie auch umgehend kommen (wenn das vorrangehende endTransmission fehlerfrei war) , es führt nur leider oft zu Fehlern wenn man zu früh anfängt mit dem Wire.read (also wenn, wie gesagt, der Puffer ausgelesen wird, er aber noch nicht mit den erforderlichen Bytes gefüllt ist).

    Bei zickigen Master-Slave-Kombinationen (z.B. anderen MCU devices, die bitbang-i2c verwenden oder vlt auch übermäßiges clock-stretching) kann das zugegebenermaßen vielleicht sinnvoll sein. Das betrifft dann aber meist andere Master, nicht Arduino-Master (z.B. Raspis oder Lego EV3 als Master ), der Arduino ist da geduldig und der cmps10/11 als Slave gehört auch nicht zu den Zicken (hab ich selber, läuft bei 100-400kHz und 1m Kabel dazwischen ohne Probleme, und zwar sowohl am Arduino als auch am Raspi.)
    http://www.mindstormsforum.de/viewto...tart=60#p69275
    Wer mag, kann ja die beiden Codes mal gegenseitig vergleichen.

    Ein delay ist in der while Schleife ebenfalls nicht nötig, Arduino-Standard-Beispiele fügen hier nie delays ein (ich wäre nicht überrascht, wenn die in der Funktion Wire.available() sowie so schon enthalten wären), daher kann man nach while() direkt die Nullanweisung ";" hinschreiben ohne irgendeinen {code} / Body/Körper.

    Sprich, so wie der Code oben steht, ist es das Arduino-Standardverfahren, hier wäre der letzte Ort, wo ich dran herum spielen würde zur Fehlersuche.

    ps,
    Sinnvoll ist es aber immer, in den Code Serial.println() einzufügen, wobei dann verschiedenste Variablenwerte schrittweise zur Kontrolle ausgegeben werden. In diesem Fall sollte man mal das Heading zur Kontrolle anzeigen lassen, und natürlich auch den ganzen Rest zu Debug-Zwecken.

    edit,
    ggf bei Fehlern im i2c-auslesen: sind die verwendeten Pullups richtig?
    welcher Arduino wird verwendet (manche haben ausreichende Pullups bereits intern verbaut, manche nicht) und ggf welche externen Pullups wurden gesteckt?
    Geändert von HaWe (14.06.2017 um 21:36 Uhr)

  2. #22
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    04.09.2011
    Ort
    Hessen
    Beiträge
    707
    Zitat Zitat von HaWe Beitrag anzeigen
    Ein delay ist in der while Schleife ebenfalls nicht nötig, Arduino-Standard-Beispiele fügen hier nie delays ein (ich wäre nicht überrascht, wenn die in der Funktion Wire.available() sowie so schon enthalten wären),
    Das ist in orignal Arduino viel simpler implementiert, ich habe gerade mal in den Sourcen nachgesehen.

    Hier Auszüge aus Wire.cpp
    Code:
    int TwoWire::available(void)
    {
      return rxBufferLength - rxBufferIndex;
    }
    available gibt nur zurück, wieviele von den vom Bus geholten Bytes noch nicht vom Sketch verarbeitet wurden.

    Alle Funktionen, die vom Bus lesen, warten bis sie fertig sind. Hier requestFrom (siehe Pfeil für die Wartestelle)
    Code:
    uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop)
    {
      if (isize > 0) {
      // send internal address; this mode allows sending a repeated start to access
      // some devices' internal registers. This function is executed by the hardware
      // TWI module on other processors (for example Due's TWI_IADR and TWI_MMR registers)
    
      beginTransmission(address);
    
      // the maximum size of internal address is 3 bytes
      if (isize > 3){
        isize = 3;
      }
    
      // write internal register address - most significant byte first 
      while (isize-- > 0)
        write((uint8_t)(iaddress >> (isize*8)));
      endTransmission(false);
      }
    
      // clamp to buffer length
      if(quantity > BUFFER_LENGTH){
        quantity = BUFFER_LENGTH;
      }
      // perform blocking read into buffer             <------------------------------  Da wartet er
      uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
      // set rx buffer iterator vars
      rxBufferIndex = 0;
      rxBufferLength = read;
    
      return read;
    }

    Eine Wire Implementierung, die im Hintergrund arbeiten kann, hat z.B. der Teensy. Aber da heißt das nicht wartende requestFrom sicherheitshalber sendRequest, um es von der blockierenden Arduino kompatiblen Variante zu unterscheiden.
    Geändert von Mxt (15.06.2017 um 08:51 Uhr) Grund: Verschrieben, es mus Wire.cpp statt Wiring.cpp heißen

  3. #23
    HaWe
    Gast
    Zitat Zitat von Mxt Beitrag anzeigen
    Das ist in orignal Arduino viel simpler implementiert, ich habe gerade mal in den Sourcen nachgesehen.

    Hier Auszüge aus Wiring.cpp
    Code:
    int TwoWire::available(void)
    {
      return rxBufferLength - rxBufferIndex;
    }
    available gibt nur zurück, wieviele von den vom Bus geholten Bytes noch nicht vom Sketch verarbeitet wurden.

    Alle Funktionen, die vom Bus lesen, warten bis sie fertig sind. Hier requestFrom (siehe Pfeil für die Wartestelle)
    Code:
    uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop)
    {
      if (isize > 0) {
      // send internal address; this mode allows sending a repeated start to access
      // some devices' internal registers. This function is executed by the hardware
      // TWI module on other processors (for example Due's TWI_IADR and TWI_MMR registers)
    
      beginTransmission(address);
    
      // the maximum size of internal address is 3 bytes
      if (isize > 3){
        isize = 3;
      }
    
      // write internal register address - most significant byte first 
      while (isize-- > 0)
        write((uint8_t)(iaddress >> (isize*8)));
      endTransmission(false);
      }
    
      // clamp to buffer length
      if(quantity > BUFFER_LENGTH){
        quantity = BUFFER_LENGTH;
      }
      // perform blocking read into buffer             <------------------------------  Da wartet er
      uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
      // set rx buffer iterator vars
      rxBufferIndex = 0;
      rxBufferLength = read;
    
      return read;
    }

    Eine Wire Implementierung, die im Hintergrund arbeiten kann, hat z.B. der Teensy. Aber da heißt das nicht wartende requestFrom sicherheitshalber sendRequest, um es von der blockierenden Arduino kompatiblen Variante zu unterscheiden.
    was also unter dem Strich ebenfalls bestätigt, dass man hinter dem while(Wire.available()....) keinen {code} mit delays - oder was auch immer - einfügen muss, was i_make_it verlangt oder ansonsten als schlechten Programmierstil ("quick and dirty") verunglimpft - und dann sogar zum Weglassen rät, was dann angeblich auch keinen Unterschied machen würde.
    Und was ebenfalls bestätigt, dass die Konstruktion
    Wire.requestFrom(CMPS10Addr , 4); // Abfrage von 4 Bytes vom CMPS10
    while (Wire.available() < 4); // Warten, bis 4 Bytes verfügbar
    völlig korrekt ist und verwendet wird, um zu warten, bis die i2c-Daten im Puffer soweit zur Verfügung stehen, dass sie anschließend von Wire.read() gelesen und weiter verarbeitet werden können.

    Wenn der OP also Probleme mit dem cmps10 hat und auch nicht von sich aus einen Fehler findet, würde ich, wie teilw. schon oben angeführt, zusammengefasst dazu raten:
    - den cmps10 Teil prüfen, ob er wirklich dem verwendeten Original-Example Code (meist wohl ursprünglich von James Henderson) entspricht, aber dann lassen wie er ist (s.z.B.: http://www.robot-electronics.co.uk/f...cmps11_i2c.ino)
    - erstmal dann diesen isolierten cmps10-Code laufen lassen, wie er im Original cmps10/11 Beispiel-Code steht, ob er dann auch wirklich wenigstens isoliert funktioniert
    - in den Code Serial.println() einzufügen, wobei dann verschiedenste Variablenwerte schrittweise zur Kontrolle ausgegeben werden. In diesem Fall sollte man mal das Heading zur Kontrolle anzeigen lassen, und natürlich auch den ganzen Rest zu Debug-Zwecken.
    - ggf bei Fehlern im i2c-auslesen die verwendeten Pullups überprüfen: welcher Arduino wird verwendet (manche haben ausreichende Pullups bereits intern verbaut, manche nicht) und ggf welche externen Pullups wurden gesteckt?

    Anm. (Thema "Nikolausi" und "Osterhasi" ):
    im Original-Code von James Henderson steht fälschlicherweise immer "bearing", das ist der falsche Name für das, was hier ausgelesen wird:
    Es handelt sich um "heading", auf deutsch "Kurs";
    bearing hingegen ist die Peilung eines (externen) Objektes relativ zum momentanen Kurs.
    Das nur zur Erklärung, warum ich immer "heading" eingesetzt habe, wo der O-Autor "bearing" verwendet hat. Das tut dem Algorithmus aber ntl keinen Abbruch.
    Geändert von HaWe (15.06.2017 um 09:17 Uhr)

Seite 3 von 3 ErsteErste 123

Ähnliche Themen

  1. Motorsteuerung über Joystick
    Von konstii im Forum Bauanleitungen, Schaltungen & Software nach RoboterNetz-Standard
    Antworten: 3
    Letzter Beitrag: 18.06.2009, 10:38
  2. LPT motorsteuerung über den drucker
    Von st0rm im Forum Motoren
    Antworten: 1
    Letzter Beitrag: 10.12.2007, 15:45
  3. Motorsteuerung über Fahrtenregler
    Von glory im Forum Motoren
    Antworten: 2
    Letzter Beitrag: 01.06.2007, 20:34
  4. Motorsteuerung über RS232/USB
    Von ama7224290 im Forum Motoren
    Antworten: 0
    Letzter Beitrag: 07.02.2007, 17:24
  5. Motorsteuerung über PI-Regler
    Von Gromit im Forum Allgemeines zum Thema Roboter / Modellbau
    Antworten: 0
    Letzter Beitrag: 19.11.2004, 22:44

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

fchao-Sinus-Wechselrichter AliExpress