AVR Duino és SPI eszköz használata

Az oldal Demopaneljeinek _hardware_ kérdései...
Avatar
csabaffy
Újonc
Újonc
Hozzászólások: 11
Csatlakozott: 2012. április 22. vasárnap, 6:00

AVR Duino és SPI eszköz használata

Hozzászólás Szerző: csabaffy »

Van egy AVR Duino panelem. Az Arduino programmal tudom programozni.
Szeretném egy nyomásmérő SPI adatvonalát olvasni vele.
Első körkérdésre azt kaptam, hogy miért nem I2C, meg hogy kössem fel a gatyám.
Szóval elbátortalanodtam, azonban valahogy meg kéne oldani.
Kezdő vagyok, szóval szívesen veszem a segítséget, cserébe szívesen tanulok.
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Hozzászólás Szerző: kapu48 »

Kezdheted is itt:

SPI library
http://arduino.cc/en/Reference/SPI
:lol:
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Hozzászólás Szerző: Robert »

Tényleg gatyakötés.

google: arduino+szenzorneve mit mond?
Avatar
csabaffy
Újonc
Újonc
Hozzászólások: 11
Csatlakozott: 2012. április 22. vasárnap, 6:00

Hozzászólás Szerző: csabaffy »

Találtam leírást a SPI-ről, meg az Arduino oldalán is van infó. Ír függvényeket, de amit sehol nem találok, hogy az AVR duino panel melyik kivezetéseit kell használni.
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Hozzászólás Szerző: kapu48 »

Még keveset Tudsz a SPI-röl!

Ez kifejezetten Arduino:
http://tronixstuff.wordpress.com/2011/0 ... e-spi-bus/
AVR151: Setup And Use of The SPI
http://www.atmel.com/Images/doc2585.pdf
Mit hova, miért?
http://winavr.scienceprog.com/avr-gcc-t ... llers.html

+ az AVR-ed adatlapja. Mert abból is van pár fajta.

Sajnos még magyar fordítás nincsen róla.

8)
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Hozzászólás Szerző: Robert »

Az SPI busz sokkal komplexebb és összetettebb, mint a I2C. Az SPI Hardwareközeli kezelését kell megvalósítani, míg az I2C esetén van önálló arduino függvényeljárás - és közel egységes kezelése a busznak...
Avatar
csabaffy
Újonc
Újonc
Hozzászólások: 11
Csatlakozott: 2012. április 22. vasárnap, 6:00

Hozzászólás Szerző: csabaffy »

Ezt a programot használom - erre redukáltam az exaples könyvtárban található SPI barométeres programját.
Van pár dolog, amit nem értek.

Ez a HSC Honeywell nyomás érzékelő SPI-je úgy működik, hogy a chip select aktiválása után az addig low clock felfut high-ra, majd amikor lefutó éle lesz, akkor lehet eltárolni a MISO lábon levő adatot.

Ez az érzékelő első 2x8 bit átküldése után akár az adatátvitel meg is szüntethető, vagyis a chip select high-ba megy.
Ha ki akarnám olvasni a további adatokat is (amiről amúgy az érzékelő adatlapja szemérmesen hallgat, ami hőmérséklet érték lehet), akkro a chip selectet nem a 16. órajel után, hanem 24., vagy a 32. után kell visszavenni.

Namost a mintaprogram a barométer olvasós, az olyan eszközt használ - gondolom, amely regiszterekben tárolja a mért adatokat.

Ez a Honeywell érzékelő pedig folytonos bitsorozatot ad (vagy vesszük el tőle - nézőpont kérdése).

No itt akadtam meg.
1. Hogyan tudnám megtanítani ennek a programnak, hogy ne regisztereket olvasson, hanem 16, 24 vagy 32 hosszú bitsorozatot.

2. Kell-e állítani a SPI.setDataMode(SPI_MODE1); -ot?

3. vajon az eredeti program (BarometricPressureSensor nevű program) miért használ hasonló adatokhoz más deklarációt? Az egyik helyen ezt írja:
unsigned int pressure_data_high =.......
a másik helyen pedig: byte pressure_data_low =.........

Idemásolom azt, ami jelenleg fut.

Kód: Egész kijelölése

/*
 HSC Honeywell nyomás érzékelő SPI olvasása
 AN kivitelnél a lábliosztás:
 1 GND
 2 Vsupply
 3 MISO
 4 SCLK
 5 SS
 6, 7, 8 - nincs használva
 
 HSC érzékelőhöz rendelt kivezetések:
 pins 10, 12, 13:
 SS: pin 10
 MOSI: pin 11 - nincs használva
 MISO: pin 12
 SCLK: pin 13
 
 created 2012 júmius 12.
 modified xxxxxxxxxxxxxxxxx
 by csabaffy Tom Igoe munkája alapján
 */

// the sensor communicates using SPI, so include the library:
#include <SPI.h>

//Sensor's memory register addresses - megöröklött változók, nem mind kell?:
const int PRESSURE = 0;   
const int PRESSURE_LSB = 0;
const byte READ = 0;
//
//az arduino panelnak megfelelően a pin 10 adja a chip select jelet
const int chipSelectPin = 10;

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

  // start the SPI library:
  SPI.begin();

  // initalize the  chip select pin:
  pinMode(chipSelectPin, OUTPUT);
  
  //SPI.setDataMode(mode)
  //Parameters
  //mode: SPI_MODE0, SPI_MODE1, SPI_MODE2, or SPI_MODE3 
  //Clock idle = low vagyis az órajel amíg várakozik, addig low,
  //az adat az órajel lefutó élénél érvényes, vagyis "active to idle (high to low)"
  //ez a Mode1
  SPI.setDataMode(SPI_MODE1);

  delay(2000);
}

void loop() {

    //readRegister beolvasná az első bytot 
    //paraméterei 
    //1. melyik regisztert, a 
    //2. hanyadik byt-tól bytesToRead nevű változó veszi át ezt a paramétert, innen gondolom.
   unsigned int pressure_data_high = readRegister(0x00, 0);   
   Serial.println("\tpressure_data_high=" + String(pressure_data_high)); 
    
    //Read the pressure data lower 16 bits:
  //unsigned int pressure_data_low = readRegister(0x00, 1);
  byte pressure_data_low = readRegister(0x00, 1);
  Serial.println("  low=" + String(pressure_data_low));    
 
 //összesítve a két byte - addig, amíg nem tudok jó értékeket látni a high és a low -n, addig ezt kivettem:
// long pressure = ((pressure_data_high << 8) | pressure_data_low);

// display the pressure - kiirást kivettem, addig, amíg jó nem lesz.:
//  Serial.println("\tPressure [Pa]=" + String(pressure));
      delay(1000);
  }
// az elmaradt if zárójele}

//Read from the HSC preasure sensor:
unsigned int readRegister(byte thisRegister, int bytesToRead ) {
  byte inByte = 0;           // incoming byte from the SPI
  unsigned int result = 0;   // result to return
  Serial.print("\t");

  // take the chip select low to select the device:
  digitalWrite(chipSelectPin, LOW);
  // send the device the register you want to read:
  //SPI.transfer(dataToSend);
  // send a value of 0 to read the first byte returned:
  result = SPI.transfer(0x0000);
  // decrement the number of bytes left to read:
 bytesToRead--;
  // if you still have another byte to read:
  if (bytesToRead > 0) {
    // shift the first byte left, then get the second byte:
    result = result << 8;
    inByte = SPI.transfer(0x01);
    // combine the byte you just got with the previous one:
    result = result | inByte;
    // decrement the number of bytes left to read:
    bytesToRead--;
  }
  // take the chip select high to de-select:
  digitalWrite(chipSelectPin, HIGH);
  // return the result:
  return(result);
}

------------- ennek eredménye az, hogy a low és a high érték is ugyanaz, valamint 7 a kezdeti érték, és 63 a legnagyobb érték.

Ez az érzékelő első két bitje egy állapotjelző bit.
Mondjuk jó lenne ezeket külön beolvasni egy -egy változóba, aztán jön 6 biten a high és utána 8 biten a low byte.

át idáig jutottam.
Mit javasoltok, illetve mit tudtok mondani a kérdéseimre?
Csaba
Avatar
csabaffy
Újonc
Újonc
Hozzászólások: 11
Csatlakozott: 2012. április 22. vasárnap, 6:00

Hozzászólás Szerző: csabaffy »

ebbe a sorba nem én illesztettem be az emotiont: // long pressure = ((pressure_data_high << 8 | pressure_data_low);

A ballra shiftelés 8-al helyett helyettesítette be < < 8
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Hozzászólás Szerző: Robert »

Programkód illesztés gomb nélkül bizony átalakul:)
a "Code" combbal nyitod és "*Code" zárja... :P
Avatar
csabaffy
Újonc
Újonc
Hozzászólások: 11
Csatlakozott: 2012. április 22. vasárnap, 6:00

Hozzászólás Szerző: csabaffy »

köszi, megvan.

Kód: Egész kijelölése


/*
 HSC Honeywell nyomás érzékelő SPI olvasása
 AN kivitelnél a lábliosztás:
 1 GND, 2 Vsupply, 3 MISO, 4 SCLK, 5 SS, 6, 7, 8 - nincs használva
 
 HSC érzékelőhöz rendelt kivezetések:
 pins 10, 12, 13:
 SS: pin 10
 MOSI: pin 11 - nincs használva
 MISO: pin 12
 SCLK: pin 13
 
 created 2012 júmius 12.
 modified xxxxxxxxxxxxxxxxx
 by csabaffy Tom Igoe munkája alapján
 irodalom: http://www.rosseeld.be/DRO/PIC/SPI_Timing.htm
 http://tronixstuff.wordpress.com/2011/05/13/tutorial-arduino-and-the-spi-bus/
 http://www.atmel.com/Images/doc2585.pdf
 
 */

// the sensor communicates using SPI, so include the library:
#include <SPI.h>

//Sensor's memory register addresses - megöröklött változók, nem mind kell?:
const int PRESSURE = 0;   
const int PRESSURE_LSB = 0;
const byte READ = 0;
//
//az arduino panelnak megfelelően a pin 10 adja a chip select jelet
const int chipSelectPin = 10;

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

  // start the SPI library:
  SPI.begin();

  // initalize the  chip select pin:
  pinMode(chipSelectPin, OUTPUT);
  
  //SPI.setDataMode(mode)
  //Parameters
  //mode: SPI_MODE0, SPI_MODE1, SPI_MODE2, or SPI_MODE3 
  //Clock idle = low vagyis az órajel amíg várakozik, addig low,
  //az adat az órajel lefutó élénél érvényes, vagyis "active to idle (high to low)"
  //ez a Mode1
  SPI.setDataMode(SPI_MODE1);

  delay(2000);
}

void loop() {

    //readRegister beolvasná az első bytot 
    //paraméterei 
    //1. melyik regisztert, a 
    //2. hanyadik byt-tól bytesToRead nevű változó veszi át ezt a paramétert, innen gondolom.
  unsigned int pressure_data_high = readRegister(0x00, 0);   
   Serial.println("\tpressure_data_high=" + String(pressure_data_high)); 
    
    //Read the pressure data lower 16 bits:
  //unsigned int pressure_data_low = readRegister(0x00, 1);
 // byte pressure_data_low = readRegister(0x00, 1);
 // Serial.println("  low=" + String(pressure_data_low));    
 
 //összesítve a két byte - addig, amíg nem tudok jó értékeket látni a high és a low -n, addig ezt kivettem:
// long pressure = ((pressure_data_high << 8) | pressure_data_low);

// display the pressure - kiirást kivettem, addig, amíg jó nem lesz.:
//  Serial.println("\tPressure [Pa]=" + String(pressure));
      delay(1000);
  }
// az elmaradt if zárójele}

//Read from the HSC preasure sensor:
unsigned int readRegister(byte thisRegister, int bytesToRead ) {
  byte inByte = 0;           // incoming byte from the SPI
  unsigned int result = 0;   // result to return
  Serial.print("\t");

  // take the chip select low to select the device:
  digitalWrite(chipSelectPin, LOW);
  // send the device the register you want to read:
  //SPI.transfer(dataToSend);
  // send a value of 0 to read the first byte returned:
byte result1 = SPI.transfer(0);
Serial.print(result1);
  // decrement the number of bytes left to read:
 //bytesToRead--;
  // if you still have another byte to read:
 // if (bytesToRead > 0) {
    // shift the first byte left, then get the second byte:
 result = result1 << 8;
byte result2 = SPI.transfer(0);
  //  inByte = SPI.transfer(0x01);
    // combine the byte you just got with the previous one:
    result = result | result2;
    // decrement the number of bytes left to read:
   // bytesToRead--;
 // }
  // take the chip select high to de-select:
  digitalWrite(chipSelectPin, HIGH);
  // return the result:
  return(result);
}
Avatar
csabaffy
Újonc
Újonc
Hozzászólások: 11
Csatlakozott: 2012. április 22. vasárnap, 6:00

Hozzászólás Szerző: csabaffy »

Szóval, hogyan lehet olvasni ezt a nagyon elmés kis szerkezetet?
Nincs regisztere, akkor mit olvasok ki?
Hogyan állítsam be, hogy 16 bitet olvasson be?
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Hozzászólás Szerző: Robert »

http://forum.sparkfun.com/viewtopic.php?f=8&t=23965

Kód: Egész kijelölése

/*
MPL115A1 sparkfun breakout baropressure meter
 SDN       : pin 7
 CSN       : pin 10
 SDI/MOSI  : pin 11
 SDO/MISO  : pin 12
 SCK       : pin 13
*/

// the sensor communicates using SPI, so include the library:
#include <SPI.h>

#define PRESH   0x80
#define   PRESL   0x82
#define   TEMPH   0x84
#define   TEMPL   0x86

#define A0MSB   0x88
#define A0LSB   0x8A
#define B1MSB   0x8C
#define B1LSB   0x8E
#define   B2MSB   0x90
#define B2LSB   0x92
#define C12MSB   0x94
#define   C12LSB   0x96

#define CONVERT   0x24   

#define chipSelectPin 10
#define shutDown 7

float A0_;
float B1_;
float B2_;
float C12_;

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

  // start the SPI library:
  SPI.begin();   

  // initalize the data ready and chip select pins:
  pinMode(shutDown, OUTPUT);
  digitalWrite(shutDown, HIGH);
  pinMode(chipSelectPin, OUTPUT);
  digitalWrite(chipSelectPin, HIGH);
  delay (10);
  
  // read registers that contain the chip-unique parameters to do the math
  unsigned int A0H = readRegister(A0MSB);
  unsigned int A0L = readRegister(A0LSB);
         A0_ = (A0H << 5) + (A0L >> 3) + (A0L & 0x07) / 8.0;
  
  unsigned int B1H = readRegister(B1MSB);
  unsigned int B1L = readRegister(B1LSB);
          B1_ = ( ( ( (B1H & 0x1F) * 0x100)+B1L) / 8192.0) - 3 ;
  
  unsigned int B2H = readRegister(B2MSB);
  unsigned int B2L = readRegister(B2LSB);
          B2_ = ( ( ( (B2H - 0x80) << 8) + B2L) / 16384.0 ) - 2 ;
  
  unsigned int C12H = readRegister(C12MSB);
  unsigned int C12L = readRegister(C12LSB);
          C12_ = ( ( ( C12H * 0x100 ) + C12L) / 16777216.0 )  ;
 }

void loop() {
   Serial.print("de druk is : ");
   Serial.println(baropPessure());
   delay(1000);
}  

//Read registers
unsigned int readRegister(byte thisRegister ) {
  unsigned int result = 0;   // result to return
  digitalWrite(chipSelectPin, LOW);
    delay(10);
    SPI.transfer(thisRegister);
    result = SPI.transfer(0x00);
  digitalWrite(chipSelectPin, HIGH);
  return(result);
}

//read pressure
float baropPessure(){
  digitalWrite(chipSelectPin, LOW);
  delay(3);
    SPI.transfer(0x24);
    SPI.transfer(0x00);
    digitalWrite(chipSelectPin, HIGH);
    delay(3);
  digitalWrite(chipSelectPin, LOW);
    SPI.transfer(PRESH);
    unsigned int presH = SPI.transfer(0x00);
        delay(3);
    SPI.transfer(PRESL);
    unsigned int presL = SPI.transfer(0x00);
        delay(3);
    SPI.transfer(TEMPH);
    unsigned int tempH = SPI.transfer(0x00);
        delay(3);
    SPI.transfer(TEMPL);
    unsigned int tempL = SPI.transfer(0x00);
        delay(3);
    SPI.transfer(0x00);
      delay(3);
  digitalWrite(chipSelectPin, HIGH);

  unsigned long press = ((presH *256) + presL)/64;
  unsigned long temp  = ((tempH *256) + tempL)/64;

  float pressure = A0_+(B1_+C12_*temp)*press+B2_*temp;
  float preskPa = pressure*  (65.0/1023.0)+50.0;

return(preskPa);
}
Avatar
csabaffy
Újonc
Újonc
Hozzászólások: 11
Csatlakozott: 2012. április 22. vasárnap, 6:00

Hozzászólás Szerző: csabaffy »

Kösz. Megnéztem, kipróbáltam.
Leegyszerűsítettem, hogy csak kettő beolvasást csináltam.
A nagyobb helyiérték nulla nyomásnál 7, az alacsonyabb byte pedig 100 körül ingadozik.

Az, hogy 100 körül ingadozik, azt megértem, hiszen 400Pa nyomás méréshatára, ami elég kicsi.
De hogy a magasabb byte miért 7-el indít, azt nem értem.
ha szívást eresztek az érzékelőre, akkor 0 lesz az értéke.
Már arra gondoltam, hogy valami számábrázolási gond lehet, de hát a 7 az a 6 bit 64-ének sehogy nem a fele, meg aztán unsigned int a deklarálása, az meg nem olyan.

most ott tartok, hogy csinálok egy mérés előtti kalibrációt, és a nullát azt korrigálom.

Összeállítok egy referencia mérést, hogy a végértékről legyen valami fogalmam.

Ha valaki ehhez a 7-es induló értékhez tud valami okosat mondani, azt megköszönném.
Csaba
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Hozzászólás Szerző: Robert »

És egyszerűsítés _nélkül_ mit csinál a program?
Avatar
csabaffy
Újonc
Újonc
Hozzászólások: 11
Csatlakozott: 2012. április 22. vasárnap, 6:00

Hozzászólás Szerző: csabaffy »

Egyszerűsítés nélkül beolvas még kettő bytot.
Ezek értéke független anyomástól.
Válasz küldése