LoRa blockt andere SPI-Verbindungen

ts7622

Ensign
Registriert
Aug. 2012
Beiträge
237
Guten Abend,

ich habe hier ein Problem an dem ich schon etwas länger sitze aber alleine scheinbar nicht weiterkomme. Ich versuche zwei Geräte über SPI zu steuern. Gerät Nummer Eins ist ein SX1278 welches über die LoRa library angesteuert wird. Das Zweite ist ein RX5808 (Ein Videoempfänger auf 5.8GHz, dessen Kanäle über SPI verändert werden können).

Nun zum Problem: Beides einzeln funktioniert ohne Probleme. Wird jedoch LoRa über LoRa.begin() initialisiert, bekomme ich keine Verbindung mehr zum RX5808. Kommentiere ich jedoch das begin aus, funktioniert es mit dem RX5808 tadellos.

Irgendwas macht die LoRa library, dass ich nicht mehr mit anderen Geräte kommunizieren kann, nur komme ich nicht hinter was es genau ist. Hatte jemand ein ähnliches Problem und/ oder kennt die Lösung?

client.ino
C:
int did;

#include <EEPROM.h>
#include <LoRa.h>

const int VRX_SPI_SELECT                = 3;
const int VRX_SPI_DATA                  = 10;
const int VRX_SPI_CLOCK                 = 12;
const int VRX_RSSI                      = 7;

const int LORA_SELECT                   = 9;
const int LORA_RESET                    = 8;
const int LORA_DATA                     = 2;

#include "lora.h";
#include "vrx.h";

using namespace lora;
using namespace vrx;

void setup() {
  Serial.begin(9600);

  pinMode(VRX_SPI_SELECT,OUTPUT);
  digitalWrite(VRX_SPI_SELECT,HIGH);
  pinMode(LORA_SELECT,OUTPUT);
  digitalWrite(LORA_SELECT,HIGH);

  vrx::init();
  lora::init();
}

void loop() {
  lora::receive();
  AutoTune();
  delay(1);
}

int highValue=0;
int highChannel=0;

void AutoTune()
{
  String txt="";
  int val=0;
  Serial.println("AutoTune");

  int count = 0;
  for(count=0;count<40;count++)
  {
    vrx::setChannel(count);
    delay(50);
    val = analogRead(A7);    // read the input pin
    if(val > highValue)
    {
      highValue=val;
      highChannel=count;
    }
    txt += String(val) + " ";
    if(count == 7 || count == 15 || count == 23 || count == 31 || count == 39) {
      txt += "\n";
    }
  }
  count=highChannel;
    vrx::setChannel(count);
  Serial.println(txt);
  Serial.println("------");
}

lora.h
C:
namespace lora {

  void send(String cmd, String val);
  void receive();

  void init() {
    LoRa.setPins(LORA_SELECT, LORA_RESET, LORA_DATA);
    if (!LoRa.begin(433E6)) {             // initialize ratio at 915 MHz
      Serial.println("LoRa init failed. Check your connections.");
      while (true);                       // if failed, do nothing
    }
    Serial.println("LoRa init succeeded.");
  }

  void send(String cmd, String val) {
    String msg = String(did) + "1000;" + cmd + ";" + val;
    Serial.println("lora tx: " + msg);
    LoRa.beginPacket();
    LoRa.write(0xFF);
    LoRa.write(0xBB);
    LoRa.write(0);
    LoRa.write(msg.length());
    LoRa.print(msg);
    LoRa.endPacket();
  }

  void receive() {
    if(String(LoRa.parsePacket()).toInt() != 0) {
      int recipient = LoRa.read();          // recipient address
      byte sender = LoRa.read();            // sender address
      byte incomingMsgId = LoRa.read();     // incoming msg ID
      byte incomingLength = LoRa.read();    // incoming msg length
   
      String incoming = "";
   
      while (LoRa.available()) {
        incoming += (char)LoRa.read();
      }
      if (incomingLength == incoming.length()) {
        Serial.println("lora rx: " + incoming);
      }
    }
  }
}

vrx.h
C:
namespace vrx {
  // channel Table
  uint16_t channelTable[] = {
  0x2a05 ,0x299b ,0x2991 ,0x2987 ,0x291d ,0x2913 ,0x2909 ,0x289f ,
  0x2903 ,0x290c ,0x2916 ,0x291f ,0x2989 ,0x2992 ,0x299c ,0x2a05 ,
  0x2895 ,0x288b ,0x2881 ,0x2817 ,0x2a0f ,0x2a19 ,0x2a83 ,0x2a8d ,
  0x2906 ,0x2910 ,0x291a ,0x2984 ,0x298e ,0x2998 ,0x2a02 ,0x2a0c ,
  0x281d ,0x2890 ,0x2902 ,0x2915 ,0x2987 ,0x299a ,0x2a0c ,0x2a1f
  };

  void SERIAL_SENDBIT1()
  {
    digitalWrite(VRX_SPI_CLOCK, LOW);
    delayMicroseconds(300);
    digitalWrite(VRX_SPI_DATA, HIGH);
    delayMicroseconds(300);
    digitalWrite(VRX_SPI_CLOCK, HIGH);
    delayMicroseconds(300);
    digitalWrite(VRX_SPI_CLOCK, LOW);
    delayMicroseconds(300);
  }

  void SERIAL_SENDBIT0()
  {
    digitalWrite(VRX_SPI_CLOCK, LOW);
    delayMicroseconds(300);
    digitalWrite(VRX_SPI_DATA, LOW);
    delayMicroseconds(300);
    digitalWrite(VRX_SPI_CLOCK, HIGH);
    delayMicroseconds(300);
   
    digitalWrite(VRX_SPI_CLOCK, LOW);
    delayMicroseconds(300);
  }

  void SERIAL_ENABLE_LOW()
  {
    delayMicroseconds(100);
    digitalWrite(VRX_SPI_SELECT,LOW);
    delayMicroseconds(100);
  }

  void SERIAL_ENABLE_HIGH()
  {
    delayMicroseconds(100);
    digitalWrite(VRX_SPI_SELECT,HIGH);
    delayMicroseconds(100);
  }

  void init() {
    pinMode (VRX_SPI_SELECT, OUTPUT);
    pinMode (VRX_SPI_DATA, OUTPUT);
    pinMode (VRX_SPI_CLOCK, OUTPUT);
    digitalWrite(VRX_SPI_SELECT, HIGH);
  }

  void setChannel(uint8_t channel)
  {
    uint8_t i;
    uint16_t channelData;
   
    // channelData = pgm_read_word(&channelTable[channel]);
    channelData = channelTable[channel];
   
    // bit bash out 25 bits of data
    // Order: A0-3, !R/W, D0-D19
    // A0=0, A1=0, A2=0, A3=1, RW=0, D0-19=0
    SERIAL_ENABLE_HIGH();
    delay(2);
    SERIAL_ENABLE_LOW();

    SERIAL_SENDBIT0();
    SERIAL_SENDBIT0();
    SERIAL_SENDBIT0();
    SERIAL_SENDBIT1();
   
    SERIAL_SENDBIT0();
   
    // remaining zeros
    for (i=20;i>0;i--)
      SERIAL_SENDBIT0();
   
    // Clock the data in
    SERIAL_ENABLE_HIGH();
    delay(2);
    SERIAL_ENABLE_LOW();

    // Second is the channel data from the lookup table
    // 20 bytes of register data are sent, but the MSB 4 bits are zeros
    // register address = 0x1, write, data0-15=channelData data15-19=0x0
    SERIAL_ENABLE_HIGH();
    SERIAL_ENABLE_LOW();
   
    // Register 0x1
    SERIAL_SENDBIT1();
    SERIAL_SENDBIT0();
    SERIAL_SENDBIT0();
    SERIAL_SENDBIT0();
   
    // Write to register
    SERIAL_SENDBIT1();
   
    // D0-D15
    //   note: loop runs backwards as more efficent on AVR
    for (i=16;i>0;i--)
    {
      // Is bit high or low?
      if (channelData & 0x1)
      {
        SERIAL_SENDBIT1();
      }
      else
      {
        SERIAL_SENDBIT0();
      }
     
      // Shift bits along to check the next one
      channelData >>= 1;
    }
   
    // Remaining D16-D19
    for (i=4;i>0;i--)
      SERIAL_SENDBIT0();
   
    // Finished clocking data in
    SERIAL_ENABLE_HIGH();
    delay(2);
   
    digitalWrite(VRX_SPI_SELECT,LOW);
    digitalWrite(VRX_SPI_CLOCK, LOW);
    digitalWrite(VRX_SPI_DATA, LOW);
  }
}
 
Ohne mir jetzt 300 Zeilen code zu gemüte zu führen, würde ich auf einen Konflikt beim Chipselect (pin3 und 9(?)) tippen. Datenübertragung darf nur jeweils mit einem Gerät passieren. während der CS des einen Gerätes low ist (sprich es findet Datenaustausch statt) muss der andere High sein. Eventuell habe ich die entprechenden Zeilen übersehen, aber ich meine, dass hier solches nirgends sichergestellt ist.
 
VRX scheint mir aber den SPI Software seitig zu emulieren da nur Daten an den Videoempfänger sendet um Kanäle einzustellen.
Dieser scheint ja auch nicht auf den gleichen Pins gemappt zu sein.

Ist es nicht möglich vom Telemetrie Empfänger die Daten via UART zu bekommen? Dann ist zumindest sicher gestellt das RX5808 allein am SPI hängt.
 
MrMcMathew schrieb:
... Konflikt beim Chipselect (pin3 und 9(?)) ... ich meine, dass hier solches nirgends sichergestellt ist.

Doch, beim wechseln des Kanals für den VRX wird am Anfang der Select Pin (Pin 3) für den RX5808 zunächst auf HIGH und kurze Zeit später auf LOW gesetzt:

C:
    SERIAL_ENABLE_HIGH();
    delay(2);
    SERIAL_ENABLE_LOW();

elchue schrieb:
Ist es nicht möglich vom Telemetrie Empfänger die Daten via UART zu bekommen? Dann ist zumindest sicher gestellt das RX5808 allein am SPI hängt.

So ohne weiteres ist das nicht möglich. Es gibt da scheinbar ein Stück Hardware was SPI zu UART konvertiert, aber da kann ich ja gleich einen weiteren Nano nehmen. Wichtig ist mir nur, dass der Code nicht stehen bleibt, wenn etwas empfangen und gesendet wird.
 
Zurück
Oben