SPI Haberleşme Yardım Lütfen
  • Merhabalar;
    Ben RM3100 manyetik sensörü ile Arduino üzerinden veri almak istiyorum. Sensör SPI destekliyor fakat ben bu konuda çok iyi değilim. Sensörün datasheet'inde SPI algoritması var. Ona uygun olarak bir kod yazmaya çalıştım fakat sürekli 33 değerini okuyorum. Yazdığım kodu aşağıda paylaşıyorum.
    Ayrıca sensörün datasheet linki: http://www.diltronic.com/wordpress/wp-content/uploads/RM3100-Sensor-Suite-User-Manual-r03.pdf
    (Datasheet sayfa 38'de algoritma mevcuttur.)

    KOD:
    #include < SPI.h>
    const int DRDY = 7;
    const int SSN = 10;
    uint8_t data;
    void setup() {

    Serial.begin(115200);
    // put your setup code here, to run once:
    SPI.begin();
    SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
    pinMode(DRDY, INPUT);
    pinMode(SSN, OUTPUT);
    }

    void loop() {
    digitalWrite(SSN,HIGH); //set cycle count register
    digitalWrite(SSN,LOW);
    SPI.transfer(0x04);
    SPI.transfer(0x00);
    SPI.transfer(0x64);
    SPI.transfer(0x00);
    SPI.transfer(0x64);
    SPI.transfer(0x00);
    SPI.transfer(0x64);
    digitalWrite(SSN,HIGH); //end of set cycle counter

    delay(100);

    digitalWrite(SSN,LOW); //CMM MODE start
    SPI.transfer(0x01);
    SPI.transfer(0x79);
    digitalWrite(SSN,HIGH);


    while(1)
    {
    measure();
    }
    }
    void measure() {
    digitalWrite(SSN,LOW);
    data=SPI.transfer(0xA4);

    Serial.println(data);

    digitalWrite(SSN,HIGH);
    //Serial.println(deger);
    delay(1000);

    }
  • Datasheet te SSN pini en az 100ns HIGH konumunda olmalı diyor. loop() un en başında ve measure fonksiyonuna girerken 1'den 0'a bekleme yapmadan iniyor. Orada zamanlama tutmamış olabilir. HIGH ve LOW arasına delay(1); koysan garanti olur.

    İkincisi ölçümleri okurken her axis için 3 byte olmak üzere toplam 9 byte okuman gerekli diyor. Sen sadece 1 byte okumuşsun diyecem ama o da olmamış. Adresten sonra bir byte daha göndermen gerekir çünkü adres giderken status geliyor, daha sonraki byte larda ise datalar geliyor.

    Üstelik veriler işaretli (signed) sayı, sen unsigned olarak okumaya çalışmışsın, yani okusan bile tümüyle anlamsız bir değer olacak yine.

    println fonksiyonu string yazıyor. Sen ise bir sayı yazmışsın, yani anlamsız bir karakter. Sonlandırma karakteri olmadığı için de 0 (NULL) görene kadar yazıp durur. Belki de sonsuz döngüye girer. Elde ettiğin sayıyı stringe dönüştürüp öyle yazman gerekiyor.
  • Öncelikle yanıtınız için teşekkür ederim.

    Zamanlama kısmındaki hatamı anladım ve buna uygun olarak delay koyacağım.

    Ölçümleri okumak için SPI.transfer(0xA4) komutundan sonra 9 adet SPI.transfer(0) yaptığım takdirde bu her eksen için 3 bit olan toplamda 9 bitlik veriyi elde eder miyim?

    Signed sayı ve unsigned sayı arasındaki farkı ne yazıkki bilmiyorum. Sorun bu değerleri println ile yazdırmaya çalışmam mı?
  • println otomatik dönüşüm yapıyormuş, orası tamam.
    3 byte'ı almak için;

    SPI.transfer(0xA4);
    int32_t axis = SPI.transfer(0);
    axis <<= 16;
    axis |= ((uint16_t) SPI.transfer(0)) << 8;
    axis |= SPI.transfer(0);
    Serial.println(axis);


    Aslında 24 bit hassaslığa gerek yoksa 8 ya da 16 bit kullanabilirsin. Ör. 8 bit (-128 | +127);
    int8_t axis = SPI.transfer(0);
    Serial.println(axis);
  • Kodu bu şekilde yazdım. Ancak serial monitorde sadece 0 değeri geliyor.
    Ayrıca sensör 3.3 V ile çalışıyor. Bunun için converter kullandım. Bundan kaynaklanan herhangi bir sorun olur mu ?


    #include < SPI.h>
    const int DRDY = 7;
    const int SSN = 6;
    int data;
    void setup() {

    Serial.begin(115200);
    // put your setup code here, to run once:
    SPI.begin();
    SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
    pinMode(DRDY, INPUT);
    pinMode(SSN, OUTPUT);
    }

    void loop() {
    digitalWrite(SSN,HIGH); //set cycle count register
    delay(1);
    digitalWrite(SSN,LOW);
    SPI.transfer(0x04);
    SPI.transfer(0x00);
    SPI.transfer(0x64);
    SPI.transfer(0x00);
    SPI.transfer(0x64);
    SPI.transfer(0x00);
    SPI.transfer(0x64);
    digitalWrite(SSN,HIGH); //end of set cycle counter

    delay(100);

    digitalWrite(SSN,LOW); //CMM MODE start
    SPI.transfer(0x00);
    SPI.transfer(0x79);
    digitalWrite(SSN,HIGH);

    delay(1);
    while(1)
    {
    measure();
    }
    }
    void measure() {
    digitalWrite(SSN,LOW);

    SPI.transfer(0xA4);
    int32_t axis = SPI.transfer(0);
    axis <<= 16;<br />axis |= ((uint16_t) SPI.transfer(0)) << 8;<br />axis |= SPI.transfer(0);
    Serial.println(axis);

    digitalWrite(SSN,HIGH);
    //Serial.println(deger);
    delay(1000);

    }
  • Buradan sorunu görebilmemiz mümkün değil. Daha önce kullandığım bişey de değil çünkü.

    Konfigurasyon hatası olabilir. Bağlantılarda parazit olabilir. Mesela ilk yazdığın 0x64 değerlerini datasheette örnek olsun diye göstermiş, default değerlerinin ideal olduğunu söylemiş. Yerinde olsam onları silerdim. Tavsiye olarak sample rate olarak düşük bir değer seç ve DRDY pinini ya da status register'ını kullan. Ör.

    SPI.transfer(0x0B);
    SPI.transfer(0x9B); // 1.2 hz tazeleme
    SPI.transfer(0xB4);
    SPI.transfer(0); // DRDY temizle
    ...

    // Veri hazır olana kadar bekle.
    do {
    SPI.transfer(0xB4);
    }
    while((SPI.transfer(0) & 0x80) == 0);

    // Okumaya hazır
    ...

    Tabi dağınık olarak yazdım ben, sen toparlarsın.
    Yine olmazsa logic analyzer kullan derim. Ben haberleşme hatalarını hep öyle bulmuşumdur.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Login with Facebook

Tagged

Açık kaynak kültürü gereği, çözdüğünüz problemlerin çözümlerini paylaşmayı lütfen unutmayın.