Arduino-esimerkkikoodi SPI-absoluuttienkoodereille
2024-10-08
Tämän Arduino-esimerkkikoodin ja oppaan tarkoituksena on antaa käyttäjille hyvä lähtökohta Same Skyn AMT22-absoluuttienkoodereiden konfigurointiin ja datan lukuun SPI (Serial Peripheral Interface) -liitännän kautta. Opas kertoo, mitä laitteita ja ohjelmistoja tarvitaan ja mitkä ovat keskeiset asetusvaiheet. Se myös sisältää esimerkkikoodipaketit ja -ohjeet sekä yksi- että monikierroksisille lähtövaihtoehdoille. Tässä on luettelo siitä, mitä tarvitaan alkuun pääsemiseksi:
- Arduino-kortti
- AMT22-enkooderi
- AMT-06C-1-036-kaapeli tai vastaava kaapeli, jossa on vaadittava liitin
- Arduino IDE
- yksikierroksisen AMT22-esimerkkikoodin lataaminen
- monikierroksisen AMT22-esimerkkikoodin lataaminen.
AMT22-absoluuttienkooderien yleiskuvaus
Same Skyn (aiemmin CUI Devices) AMT22 on absoluuttienkooderi, jota tarjotaan joko 12- tai 14-bittisellä resoluutiolla, mikä tarkoittaa, että se tarjoaa tarkan lukumäärän uniikkeja pisteitä kierrosta kohti. 12-bittisessä versiossa tämä tarkoittaa 4 096 uniikkia pistettä, kun taas 14-bittinen malli tarjoaa 16 384 pistettä kierrosta kohti. Riippumatta siitä, kuinka monta kertaa laitteen akseli pyörii ympäri, se ilmoittaa koko ajan absoluuttisen asentonsa ja antaa käyttäjille täsmällistä palautetta laitteen tarkasta kulmasta.
Tätä enkooderia on saatavana sekä yksikierroksisena että monikierroksisena mallina. Yksikierroksinen version mittausalue on 360 astetta, kun taas monikierroksinen versio kertoo sekä asennon että täysien kierrosten kokonaismäärän. Yksikierroksisen version ominaisuuksiin kuuluu lisäksi ohjelmoitava nollapiste, jonka avulla käyttäjät voivat määrittää enkooderin alkupisteen haluttuun kohtaan.
Aloitus
Varmista, että laite on RUN-tilassa asettamalla enkooderin takana oleva kytkin haluttuun asentoon (kuva 1). Asenna AMT22-enkooderi sitten moottoriin tai kokoonpanoon AMT:n asennusohjeiden mukaisesti. AMT22-enkooderi tukee 9 erilaista akselikokoa 2 mm – 8 mm.
Kuva 1: Aseta AMT22-enkooderin takana oleva kytkin RUN-tilaan. (Kuvan lähde: Same Sky)
Kuvassa 2 ja taulukossa 1 esitetyt liitännät on tarkoitettu erityisesti Arduino Uno -kortille, mutta esimerkkikoodin pitäisi olla yhteensopiva useimpien Arduino-korttien kanssa. Muista kuitenkin, että nastakonfiguraatiot voivat poiketa toisistaan eri Arduino-malleissa. Katso tiedot muiden piirilevyjen liitännöistä niiden Arduino-dokumentaatiosta.
Kuva 2: Arduino Unon ja AMT22-enkooderin välinen kytkentä. (Kuvan lähde: Same Sky)
|
Taulukko 1: Arduino Unon kytkennän tiedot. (Kuvan lähde: Same Sky)
AMT22-enkooderi alkaa lähettämään absoluuttista asentodataa heti, kun SPI-viestintä alkaa. Näin perinteistä komento-vastaus-rakennetta ei tarvita. SPI-siirron ensimmäisen tavun aikana isäntä lähettää arvon 0x00 ja AMT22 vastaa heti validilla asentotiedolla.
Jos isännän on annettava komento (taulukko 2), kuten nolla-asetuskomento, se lähetetään siirron toisessa tavussa. Tätä kutsutaan laajennetuksi komennoksi. Katso lisätietoja AMT22:n teknisistä tiedoista.
|
Taulukko 2: AMT22-komentojen määritys (Kuvan lähde: Same Sky)
Koodiopas – include- ja define-rivit
Koska AMT22-enkooderin rajapintana käytetään Arduinon SPI-väylää, koodin on luettava SPI-kirjasto mukaan. Asentotietojen lähetykseen Arduinosta tietokoneeseen käytetään Arduino IDE:n sisäänrakennettua USB-sarjaliitäntää, jonka baudinopeudeksi on konfiguroitu 115200.
Lisäksi on määriteltävä AMT22:n käyttämät komennot. Koska enkooderi ei käsittele ensimmäisen tavun sisältöä, viestintäprosessin yksinkertaistamiseksi määritellään NOP (no-operation) (listaus 1).
Kopioi
/* Include the SPI library for the arduino boards */
#include <SPI.h>
/* Serial rates for UART */
#define BAUDRATE 115200
/* SPI commands */
#define AMT22_NOP 0x00
#define AMT22_ZERO 0x70
#define AMT22_TURNS 0xA0
Listaus 1: SPI-rajapinnan määrittely.
Alustaminen
Setup()-funktio (listaus 2) aloittaa alustamalla kaikki tarvittavat SPI-nastat ja konfiguroimalla sarjaliitännät viestintää varten.
Sarjaportti on alustettava, jotta datasiirto isäntäkoneeseen on mahdollista. Tämä tehdään välittämällä määritelty BAUDRATE-arvo funktioon Serial.begin().
Varmista ennen SPI:n käyttöönottoa, että Chip Select (CS) -linja on asetettu haluttuun tilaan. Tämä valmistaa enkooderin viestintää varten.
Valitse SPI-väylän kellotaajuus viestintään AMT22-enkooderin kanssa. Prototyyppivaiheessa kellotaajuudeksi riittää 500 kHz, vaikka AMT22-enkooderi tukee jopa nopeutta 2 MHz. Taajuudeksi voidaan asettaa 500 kHz käyttämällä jakamiseen arvoa SPI_CLOCK_DIV32. Koska Arduino Uno käyttää 16 MHz:n kelloa, tämä jakoarvo asettaa SPI-kellotaajuudeksi 500 kHz. Katso lisätietoja SPI-kellon konfiguroinnista Arduino-dokumentaatiosta.
Kun kaikki on konfiguroitu, SPI-väylä voidaan alustaa käyttämällä SPI.begin()-funktiota, joka asettaa kolme dedikoitua SPI-nastaa, MISO, MOSI ja SCLK, ja valmistelee järjestelmän viestintään enkooderin kanssa.
Kopioi
void setup()
{
uint8_t cs_pin = 2;
//Set the modes for the SPI CS
pinMode(cs_pin, OUTPUT);
//Get the CS line high which is the default inactive state
digitalWrite(cs_pin, HIGH);
//Initialize the UART serial connection for debugging
Serial.begin(BAUDRATE);
//set the clockrate. Uno clock rate is 16Mhz, divider of 32 gives 500 kHz.
//500 kHz is a good speed for our test environment
//SPI.setClockDivider(SPI_CLOCK_DIV2); // 8 MHz
//SPI.setClockDivider(SPI_CLOCK_DIV4); // 4 MHz
//SPI.setClockDivider(SPI_CLOCK_DIV8); // 2 MHz
//SPI.setClockDivider(SPI_CLOCK_DIV16); // 1 MHz
SPI.setClockDivider(SPI_CLOCK_DIV32); // 500 kHz
//SPI.setClockDivider(SPI_CLOCK_DIV64); // 250 kHz
//SPI.setClockDivider(SPI_CLOCK_DIV128); // 125 kHz
//start SPI bus
SPI.begin();
}
Listaus 2: Setup()-funktio, joka alustaa kaikki SPI-nastat.
SPI-viestintä
SPI-viestintä AMT22-enkooderin kanssa hoidetaan Arduinon SPI-kirjaston kautta, kun taas Chip Select (CS) -ohjausta hallitaan koodissa käyttämällä digitaalisia I/O-nastoja. DigitalWrite()-funktiota käytetään CS-linjan aktivointiin ja deaktivointiin (listaus 3).
AMT22-enkooderi odottaa, että sille lähetetään kaksi 0x00-tavua, ja palauttaa datan välittömästi vastaanotettuaan nämä tavut. Tämä nopea vaste vaatii ajoituksessa tiettyjen vähimmäisvaatimuksien täyttämistä. Nämä on määritetty AMT22-enkooderin teknisissä tiedoissa.
Enkooderi vastaa aina kahdella datatavulla (16 bittiä) riippumatta siitä, onko enkooderi 12- vai 14-bittinen versio. Kaksi ylempää bittiä ovat tarkistusbittejä, joita käytetään tiedon eheyden tarkistamiseen. 12-bittisessä versiossa kaksi alempaa bittiä ovat molemmat 0, ja palautettavaa arvoa on siirrettävä oikealle 2 bittiä (tai jaettava luvulla 4), ennen kuin arvoa voidaan käyttää.
Asentotietoja pyydetään kutsumalla SPI.transfer()-funktiota, joka lähettää AMT22_NOP-komennon. CS-linja on alhaalla tämän prosessin aikana. AMT22-enkooderi lähettää ensin enemmän merkitsevän tavun, joten vastaanotettua tavua siirretään vasemmalle 8 bittiä. Näin se voidaan kirjoittaa uint16_t-muuttujan ylempään puoliskoon. Tämä arvo sijoitetaan encoderPosition-muuttujaan yhdessä operaatiossa. Kun lyhyt viive on kulunut ajoitusvaatimusten täyttämiseksi, suoritetaan toinen SPI.transfer()-kutsu toisen AMT22_NOP-komennon lähettämiseksi. Funktiokutsun tulokselle suoritetaan TAI-operaatio encoderPosition-arvon kanssa ja tämä tulos kirjoitetaan encoderPosition-muuttujaan, jolloin kaksi vastaanotettua tavua yhdistetään yhdeksi uint16_t-muuttujaksi. Lopuksi CS-linja vapautetaan, jolloin viestintä päättyy.
Kopioi
uint8_t cs_pin = 2;
//set the CS signal to low
digitalWrite(cs_pin, LOW);
delayMicroseconds(3);
//read the two bytes for position from the encoder, starting with the high byte
uint16_t encoderPosition = SPI.transfer(AMT22_NOP) << 8; //shift up 8 bits because this is the high byte
delayMicroseconds(3);
encoderPosition |= SPI.transfer(AMT22_NOP); //we do not need a specific command to get the encoder position, just no-op
//set the CS signal to high
digitalWrite(cs_pin, HIGH);
Listaus 3: SPI-viestinnän määritys.
Tarkistussumman tarkistaminen
Kun SPI-siirto on suoritettu loppuun, on tärkeää validoida vastaanotetut tiedot tarkistussumman avulla (listaus 4).
Tätä validointia varten voidaan luoda funktio, joka perustuu teknisissä tiedoissa annettuun yhtälöön. Tarkistussumma sisältyy vastaanotetun arvon kahteen ylempään bittiin, ja se käyttää paritonta pariteettia asentovastauksen parittomissa ja parillisissa biteissä.
Funktio suorittaa seuraavat vaiheet:
- Pariteetin laskenta parittomille biteille (bitit 1, 3, 5, 7, 9, 11, 13)
- Pariteetin laskenta parillisille biteille (bitit 0, 0, 2, 4, 6, 8, 10, 12)
- Laskettujen pariteettien vertaaminen tarkistussummabittien arvoihin
Funktio palauttaa arvon true, jos tarkistussumma on oikein. Tämä vahvistaa tiedon eheyden. Jos tarkistussumma ei vastaa laskettua pariteettia, funktio palauttaa arvon false. Tämä tarkoittaa, että vastaanotettu data saattaa olla virheellistä.
Kopioi
/*
* Using the equation on the datasheet we can calculate the checksums and then make sure they match what the encoder sent.
*/
bool verifyChecksumSPI(uint16_t message)
{
//checksum is invert of XOR of bits, so start with 0b11, so things end up inverted
uint16_t checksum = 0x3;
for(int i = 0; i < 14; i += 2)
{
checksum ^= (message >> i) & 0x3;
}
return checksum == (message >> 14);
}
Listaus 4: Tarkistussumman validointi.
Datan formatointi
Jos tarkistussumman validointi vahvistaa tiedon olevan ehyttä, seuraava vaihe on encoderPosition-muuttujan päivittäminen poistamalla kaksi ylempää bittiä (listaus 5). Tämä voidaan saavuttaa suorittamalla bittikohtainen JA-operaatio luvun 0x3FFF (tai 0b0011111111111111) kanssa, jolloin asentotietojen kaikki 14 alempaa bittiä jäävät voimaan.
Lisäksi täytyy ottaa huomioon enkooderin resoluutio, 12 tai 14 bittiä. Jos resoluutio on 12 bittiä, encoderPosition-arvoa on siirrettävä 2 bittiä oikealle pienemmän resoluution korjaamiseksi. Näin encoderPosition-muuttuja esittää asentodatan tarkasti ja vastaa enkooderin todellista asentoa sille määritellyn resoluution perusteella.
Kopioi
if (verifyChecksumSPI(encoderPosition)) //position was good
{
encoderPosition &= 0x3FFF; //discard upper two checksum bits
if (RESOLUTION == 12) encoderPosition = encoderPosition >> 2; //on a 12-bit encoder, the lower two bits will always be zero
Serial.print(encoderPosition, DEC); //print the position in decimal format
Serial.write('\n');
}
else //position is bad
{
Serial.print("Encoder position error.\n");
}
Listaus 5: encoderPosition-muuttujan päivittäminen.
Nolla-asennon asettaminen (vain yksikierrosmallit)
AMT22-enkooderin tietyt versiot mahdollistavat nollakohdan asettamisen. Tämän nollakohdan asettamiseksi täytyy lähettää tietty kaksitavuinen komentosarja. Prosessissa lähetetään ensin AMT22_NOP-komento ja sen jälkeen odotetaan hetki, jotta AMT22-enkooderin määrittelemät vähimmäisaikavaatimukset täyttyvät. Tämän odotuksen jälkeen lähetetään AMT22_ZERO-komento ja samalla varmistetaan, että Chip Select -linja (CS) vapautetaan. Kun enkooderi vastaanottaa tämän komennon, se suorittaa nollaustoiminnon (listaus 6).
Tämän nollausjakson aikana voidaan välttää viestintää enkooderin kanssa käyttämällä 250 ms:n viivettä. Tämä viive varmistaa, ettei enkooderille lähetetä komentoja sen käynnistysaikana.
Vaikka koodillisesti onkin mahdollista asettaa enkooderin nollakohta alettaessa käyttää sitä, tyypillisissä sovelluksissa on tavallisempaa asettaa nollakohta vain kerran, silloin kun laite konfiguroidaan ensi kertaa käytettäväksi järjestelmässä. Tämä käytäntö auttaa säilyttämään enkooderin asentopalautteen yhdenmukaisena koko sen käyttöiän ajan.
Kopioi
/*
* The AMT22 bus allows for extended commands. The first byte is 0x00 like a normal position transfer,
* but the second byte is the command.
* This function takes the pin number of the desired device as an input
*/
void setZeroSPI(uint8_t cs_pin)
{
//set CS to low
digitalWrite(cs_pin, LOW);
delayMicroseconds(3);
//send the first byte of the command
SPI.transfer(AMT22_NOP);
delayMicroseconds(3);
//send the second byte of the command
SPI.transfer(AMT22_ZERO);
delayMicroseconds(3);
//set CS to high
digitalWrite(cs_pin, HIGH);
delay(250); //250 millisecond delay to allow the encoder to reset
}
Listaus 6: Yksikierroksisen AMT22-enkooderin nollakohdan asettaminen.
Kierroslaskurin lukeminen (vain monikierrosmallit)
Eräät AMT22-enkooderin variantit tukevat monikierroslaskuria, jolloin käyttäjät voivat lukea sekä asennon että kierrosmäärän yhdellä ainoalla tiedonhakusekvenssillä.
Jos vastaanotettu asentodata ei ole validia, järjestelmän tulisi ilmoittaa käyttäjälle virheestä. Jos asento on sisävastoin validi, ohjelman tulisi ilmoittaa asento desimaalimuodossa (listaus 7). Tämä ominaisuus parantaa enkooderin toiminnallisuutta tarjoamalla kattavaa palautetta sekä absoluuttisesta asennosta että täysien kierrosten määrästä. Se helpottaa tarkempaa valvontaa ja ohjausta sovelluksissa, jotka vaativat tarkkaa pyörimisdataa.
Kopioi
uint8_t cs_pin = 2;
//set the CS signal to low
digitalWrite(cs_pin, LOW);
delayMicroseconds(3);
//read the two bytes for position from the encoder, starting with the high byte
uint16_t encoderPosition = SPI.transfer(AMT22_NOP) << 8; //shift up 8 bits because this is the high byte
delayMicroseconds(3);
encoderPosition |= SPI.transfer(AMT22_TURNS); //we send the turns command (0xA0) here, to tell the encoder to send us the turns count after the position
//wait 40us before reading the turns counter
delayMicroseconds(40);
//read the two bytes for turns from the encoder, starting with the high byte
uint16_t encoderTurns = SPI.transfer(AMT22_NOP) << 8; //shift up 8 bits because this is the high byte
delayMicroseconds(3);
encoderTurns |= SPI.transfer(AMT22_NOP);
delayMicroseconds(3);
//set the CS signal to high
digitalWrite(cs_pin, HIGH);
Listaus 7: encoderPosition-muuttujan ja kierroslaskurin luku monikierroksisessa AMT22-enkooderissa.
Koodin suorittaminen
Kun koodi on luotu onnistuneesti, on aika ladata se Arduinoon ja luoda yhteys AMT22-enkooderiin.
Voit seurata laitteen tulosteita avaamalla sarjamonitorin Arduino IDE -ympäristössä ja varmistamalla, että tiedonsiirtonopeudeksi on asetettu 115200 baudia. Näin käyttäjät voivat seurata enkooderin toimintaa ja nähdä raportoidut asentotiedot reaaliajassa. Kun sarjamonitori on aktiivinen, enkooderin pitäisi alkaa lähettää asentotietoja. Näin sen toimintaa järjestelmässä on helppo seurata (kuva 3).
Kuva 3: Enkooderin raportoima asento, jonka Arduino vastaanottaa (kuvalähde: Same Sky)
Useita enkoodereita
Yksi SPI-laitteen käytön tarjoama merkittävä etu on mahdollisuus viestiä useiden enkoodereiden kanssa samassa väylässä. Tämän helpottamiseksi kullekin enkooderille täytyy varata oma digitaalinen I/O-nastansa, joka mahdollistaa kunkin sirun CS-ohjauksen.
Esimerkkikoodissa (listaus 8) käytetään CS-nastataulukkoa tukemaan haluttua määrää enkoodereita. Tämä ratkaisu mahdollistaa skaalautuvan viestinnän, jolloin käyttäjä voi helposti lisätä enkoodereita tarpeen mukaan. Muokkaamalla funktioita niin, että ne ottavat vastaan haluttua laitetta vastaavan nastanumeron, koodi voi ohjata dynaamisesti sitä, mikä enkooderi on aktiivinen SPI-väylässä, ja varmistaa, että jokaista laitetta voidaan käyttää erikseen.
Kopioi
uint8_t cs_pins[] = {2}; //only one encoder connected, using pin 2 on arduino for CS
//uint8_t cs_pins[] = {2, 3}; //two encoders connected, using pins 2 & 3 on arduino for CS
Listaus 8: Taulukon määritys useiden enkoodereiden lukua varten.
Seuraavassa vaiheessa käydään läpi jokainen taulukossa oleva CS-nasta ja luetaan asento jokaisesta yhdistetystä enkooderista. Näin järjestelmä voi aktivoida jokaisen enkooderin aktivoimalla sen CS-linjan, suorittamalla SPI-siirron ja pyytämällä asentotiedot. Koodi valitsee peräkkäin jokaisen enkooderin, suorittaa SPI-viestinnän ja vapauttaa CS-linjan ja varmistaa näin, että kaikkien yhdistettyjen laitteiden asentotiedot kysytään (listaus 9).
Kopioi
void loop()
{
for(int encoder = 0; encoder < sizeof(cs_pins); ++encoder)
{
uint8_t cs_pin = cs_pins[encoder];
//set the CS signal to low
digitalWrite(cs_pin, LOW);
delayMicroseconds(3);
//read the two bytes for position from the encoder, starting with the high byte
uint16_t encoderPosition = SPI.transfer(AMT22_NOP) << 8; //shift up 8 bits because this is the high byte
delayMicroseconds(3);
encoderPosition |= SPI.transfer(AMT22_NOP); //we do not need a specific command to get the encoder position, just no-op
//set the CS signal to high
digitalWrite(cs_pin, HIGH);
if (verifyChecksumSPI(encoderPosition)) //position was good, print to serial stream
{
encoderPosition &= 0x3FFF; //discard upper two checksum bits
if (RESOLUTION == 12) encoderPosition = encoderPosition >> 2; //on a 12-bit encoder, the lower two bits will always be zero
Serial.print("Encoder #");
Serial.print(encoder, DEC);
Serial.print(" position: ");
Serial.print(encoderPosition, DEC); //print the position in decimal format
Serial.write('\n');
}
else //position is bad, let the user know how many times we tried
{
Serial.print("Encoder #");
Serial.print(encoder, DEC);
Serial.print(" position error.\n");
}
}
//For the purpose of this demo we don't need the position returned that quickly so let's wait a half second between reads
//delay() is in milliseconds
delay(500);
}
Listaus 9: encoderPosition-muuttujan luku useista enkoodereista.
Tiedonsiirron jälkeen tarvitaan minimi odotusaika ennen CS-linjan vapauttamista. Komponentin teknisten tietojen mukaan tämä vähimmäisaika on 3 mikrosekuntia. Vaikka tämä viive ikään kuin tulee itsestään hitaammilla tiedonsiirtonopeuksilla, on hyvä käytäntö toteuttaa se eksplisiittisesti koodissa. Tämä parantaa laitteen toimintaa ja ajoitusmääritysten noudattamista. Tämä takaa luotettavan viestinnän AMT22-enkooderin kanssa.
Yhteenveto
Käyttäjillä pitäisi nyt olla perustiedot Same Skyn AMT22-absoluuttienkoodereiden konfiguroinnista ja datan lukemisesta. Tämä artikkeli keskittyy AMT22-absoluuttienkoodereihin. Same Skyllä on myös modulaaristen AMT-enkoodereiden sarja, joka tarjoaa erilaisia inkrementaalisia, absoluuttisia ja kommutoivia versioita.
Disclaimer: The opinions, beliefs, and viewpoints expressed by the various authors and/or forum participants on this website do not necessarily reflect the opinions, beliefs, and viewpoints of DigiKey or official policies of DigiKey.

