Använda en Accelerometer och gyroskop med Arduino



jag köpte nyligen en kombination 3 axlig accelerometer och 2 axis gyroskop från Sparkfun och jag ville lägga upp några av koden jag brukade få det igång. Jag planerar att använda den i en Arduino baserad MIDI-controller som jag kommer att utstationering snart (video nedan, koden på botten av sidan), jag vill använda de analoga kontrollerna från tilt och rotationsrörelse för att kontrollera den utgående MIDI. Accelerometrar och gyroskop används också ofta på robotar för att balansera och andra typer av feedback.

Först lite grundläggande information:
Gyroskop mäter rotationsrörelse i grader per sekund. De kommer inte direkt säga information om tilt, enda rörelse kring en axel. Accelerometrar mäter acceleration, kan du enkelt använda denna information för att beräkna lutningen på ett objekt genom att dra ifrån aktuella accelerometer data från ett värde som du vet är noll tilt.

För detta projekt använde jag 5 frihetsgrader IDG500/ADXL335 styrelse från Sparkfun. Jag gillar detta forum eftersom det visar accelerometer och gyroskop informationen som 5 analoga spänningar som enkelt kan läsas med hjälp av fem av de Arduino analog ingång stift. Några accelerometrar och gyroskop utgång data digitalt genom att koda det i en puls-bredd modulerad signal (PWM). Om du är kort på analog ingång stift på din Arduino, det kan vara en bra idé att använda en av dessa digitala marker, men den analoga chips är trevligt eftersom de kräver minimal ansträngning att få arbeta.

Reservdelslista:
IMU analoga Combo styrelse - 5 frihetsgrader IDG500/ADXL335 Sparkfun SEN-11072
Arduino Uno Sparkfun DEV-11021
manliga header pins Sparkfun PRT-00116
22 gauge tråd
skärbräda

Så här:

Löda header pins till accelerometer/gyro ombord. På en skärbräda Anslut Arduino 5V till "RAW" stift, Arduino mark till mark, sedan stift märkt X Acc till A0, Y-Acc till A1, och Z-enl A2

Koden nedan visar X, Y och Z accelerationen fro din styrelse i följetong monitor (ctrl/Kommando + Skift + M). Jag försökte att centrera värdena runt en nollpunkt genom att införa variabeln "noll" i min kod och sedan subtrahera alla mina inkommande data från detta nummer. Detta sätt när styrelsen hålls parallellt med marken, läsa X och Y accelerationen både 0. När styrelsen tippas positiva X kommer den att visa ett positivt tal, och när det tippas negativa X visas ett negativt tal (detsamma gäller Y). Denna accelerometer kod kan du bestämma inriktningen på din bräda i 3D-rymden.

Analoga Accerometer w följetong
av Amanda Ghassaei

Augusti 2012

/*
* Detta program är fri programvara; Du kan vidaredistribuera det och/eller ändra
* det enligt villkoren i GNU General Public License som offentliggjorts av
* den Free Software Foundation; antingen version 3 av licensen, eller
* (på ditt alternativ) någon senare version.
*
*/

setup upp accerleation variabler
int xAcc;
int yAcc;
int zAcc;

int noll = 282; //this var noll punkt värdet för min accelerometer, din styrelse kan vara något annorlunda. se kommentaren nedan för att beräkna detta med en egen styrelse.

void setup() {
Serial.BEGIN (9600); //set upp följetong
}

void loop() {

Läs värden
xAcc = analogRead(A0);
yAcc = analogRead(A1);
zAcc = analogRead(A2);

/**
Om du vill bestämma noll punkt för din styrelse,
kommentera ut de sista åtta raderna i denna slinga och avkommentera raderna nedan.
Håller styrelsen parallellt med marken och titta på seriell övervaka,
xAcc och yAcc värdena kommer att sväva runt ett gemensamt värde,
Detta är din "noll" värde. Ändra värdet för den variabel "zero" ovan.
**/
//Print värden
Serial.Print ("xAcc");
Serial.println(xAcc);
Serial.Print ("yAcc");
Serial.println(yAcc);
Serial.Print ("zAcc");
Serial.println(zAcc);
Serial.println("");
fördröjning (500), //wait

skriva ut värden
Serial.Print ("xAcc");
Serial.println(Zero-xAcc);
Serial.Print ("yAcc");
Serial.println(Zero-yAcc);
Serial.Print ("zAcc");
Serial.println(Zero-zAcc);
Serial.println("");
fördröjning (500), //wait

}

Ibland kan du använda ett gyroskop för att få roterande information om din styrelse som inte kan beräknas med en accelerometer. Anslut stift märkt Vref till A0, yRate till A1, xRate till A2, y4.5 till A3 och x4.5 till A4 på en skärbräda.
Du kanske undrar om skillnaden mellan X / YRate och X / Y4.5 utgångar. Gyroskop mäter grader per sekund, denna gyroskop utgångar en spänning baserat på graden av rörelse per sekund så vi kan säga att det mata volt per grader per sekund (V / ° / s). Från databladet för gyroskopet kan vi se att X / YRate mata ut data med 2.0mV/°/s känslighet och X / Y4.5 mata ut data med ca 4,5 gånger känslighet eller 9.1mV/°/s.
Ladda upp följande kod för att visa utdata från var och en av dessa (fig 6).

Analoga Gyro w följetong
av Amanda Ghassaei

Augusti 2012

/*
* Detta program är fri programvara; Du kan vidaredistribuera det och/eller ändra
* det enligt villkoren i GNU General Public License som offentliggjorts av
* den Free Software Foundation; antingen version 3 av licensen, eller
* (på ditt alternativ) någon senare version.
*
*/

setup variabler för gyroskop
int xRate;
int x45;
int yRate;
int y45;
int Vref;

void setup() {
Serial.BEGIN (9600); //start seriell
}

void loop() {

Läs värden
x45 = analogRead(A4);
y45 = analogRead(A3);
xRate = analogRead(A2);
yRate = analogRead(A1);
VREF = analogRead(A0);

skriva ut värden
Serial.Print ("xRate");
Serial.println(xRate);
Serial.Print ("yRate");
Serial.println(yRate);
Serial.Print ("Vref");
Serial.println(VREF);
Serial.Print ("x4.5");
Serial.println(x45);
Serial.Print ("y4.5");
Serial.println(y45);
Serial.println("");

Delay(500);

}

Jag ville noll denna kod som jag gjorde med accelerometer koden ovan. Jag väntade utgångarna från x och y gyro till lika utdata från Vref medan enheten hålls stationära, men som ni kan se i bild 6, detta är inte fallet (om någon har en förklaring till detta jag skulle älska att höra det!). Eftersom Vref inte var Gud referens för mig noll min utgång till, jag använde några förinställda värden baserade på data från fig 6, du hittar dem i mina print uttalanden i koden nedan. Jag tog också bort övervakning av Vref eftersom det verkade vara stabil oavsett hur mycket jag flyttade enheten, här också bevarat jag en analog ingångsstift på Arduino.

Analoga Gyro w följetong
av Amanda Ghassaei

Augusti 2012

/*
* Detta program är fri programvara; Du kan vidaredistribuera det och/eller ändra
* det enligt villkoren i GNU General Public License som offentliggjorts av
* den Free Software Foundation; antingen version 3 av licensen, eller
* (på ditt alternativ) någon senare version.
*
*/

setup variabler för gyroskop
int xRate;
int x45;
int yRate;
int y45;
int Vref;

void setup() {
Serial.BEGIN (9600); //start seriell
}

void loop() {

Läs värden
x45 = analogRead(A4);
y45 = analogRead(A3);
xRate = analogRead(A2);
yRate = analogRead(A1);
VREF = analogRead(A0);

skriva ut värden
Serial.Print ("xRate");
Serial.println(287-xRate);
Serial.Print ("yRate");
Serial.println(256-yRate);
Serial.Print ("x4.5");
Serial.println(317-x45);
Serial.Print ("y4.5");
Serial.println(172-y45);
Serial.println("");

Delay(500);

}

Resultaten från denna kod visas i figur 7. Rotation kring x- och y axlarna kommer att ändra värdena för xRate, x4.5, yRate och y4.5.
Jag använde denna accelerometer/gyro i en Arduino-baserad MIDI-controller jag jobbat på. Nedan är koden för de två programmen jag demoed i videon på toppen av detta instructable. Jag kopplade alla tre axlarna av accelerometern och de två 4.5gyro utgångarna för detta projekt.

enstaka pixel flyttar, utlösa MIDI (använder bara x och y accelerometer):

Accelerometer test-singel pixel
Amanda Ghassaei 2012

/*
* Detta program är fri programvara; Du kan vidaredistribuera det och/eller ändra
* det enligt villkoren i GNU General Public License som offentliggjorts av
* den Free Software Foundation; antingen version 2 av licensen, eller
* (på ditt alternativ) någon senare version.
*
*/

PIN-anslutningar
#define ledLatchPin 6
#define ledClockPin 5
#define ledDataPin 7
#define buttonLatchPin 4
#define buttonClockPin 3
#define buttonDataPin 2

installationsprogrammet för varibles för gyroskop/Accelerometer
int xGyroRAW;
int yGyroRAW;
int xAccRAW;
int yAccRAW;
int zAccRAW;

byte xGyro;
byte yGyro;
byte xAcc;
byte yAcc;
byte zAcc;

looping variabler
byte i.
byte j;
byte k;

lagring för ledde staterna, 4 byte
byte ledData [] = {0, 0, 0, 0};
lagring för knappar, 4 byte
byte buttonCurrent [] = {0,0,0,0}.
byte buttonLast [] = {0,0,0,0}.
byte buttonEvent [] = {0,0,0,0}.
byte buttonState [] = {0,0,0,0}.
knappen Dämpningstid counter - 16 byte
byte buttonDebounceCounter [4] [4].

variabler för accelerometer pixel rörelse
booleska firstPress = 1;
byte movingPixel [] = {0, 0, 0, 0};
byte yPosition;
byte xPosition;
int timeX = 0;
int timeY = 0;
booleska dirX = 0;
booleska dirY = 0;
byte lastX = 4;
byte lastY = 4;

MIDI-variabler
int hastighet = 100;
int noteON = 144;
int MIDIoffset = 60.
byte AktuelltX;

void setup() {

DDRD = 0xFA; //set stift D7-D4 som D2 som indata-utdata

Serial.BEGIN (31250); //MIDI överföringshastighet
Serial.BEGIN(9600);

(CLI); //stop avbrott

Ställ in timer1 avbrott vid 1kHz
TCCR1A = 0; / / Ställ in hela TCCR1A register till 0
TCCR1B = 0; / / samma för TCCR1B
TCNT1 = 0, //initialize counter värde till 0.
ställa in timer räknas 1khz steg
OCR1A = 1999. / / = (16 * 10 ^ 6) / (1000 * 8) - 1
Aktivera CTC läge
TCCR1B | = (1 << WGM12);
Ange CS11 bit för 8 prescaler
TCCR1B | = (1 << CS11);
Aktivera timern jämför avbrott
TIMSK1 | = (1 << OCIE1A);

SEI (); //allow avbrott

}

ISR(TIMER1_COMPA_vect) {//Interrupt på freq 1 kHz
timeX ++; //increment timeX
timeY ++; //increment timeY
Skift (); //send data till lysdioder
}

buttonCheck - kontrollerar status för en viss knapp.
denna buttoncheck funktion är i stort sett kopierade från monome 40h firmware brian crabtree och joe sjö
void buttonCheck (byte rad, byte index)
{
om (((buttonCurrent [rad] ^ buttonLast[row]) & (1 << index)) & & / / om det aktuella fysiska knapp läget skiljer sig från den
((buttonCurrent [rad] ^ buttonState[row]) & (1 << index))) {/ / last fysisk knapp staten och nuvarande debounced staten

om (buttonCurrent [rad] & (1 << index)) {/ / om nuläget fysisk knapp trycks
buttonEvent [rad] = 1 << index; köa upp en ny knapp händelse omedelbart
buttonState [rad] | = (1 << index); och ställa in debounced ner.
}
annat {
buttonDebounceCounter [rad] [index] = 12.
} / / annars knappen tidigare var deprimerad och nu
har släppts så vi våra debounce counter.
}
annars om (((buttonCurrent [rad] ^ buttonLast[row]) & (1 << index)) == 0 & & / / om det aktuella fysiska knapp läget är samma som
(buttonCurrent [rad] ^ buttonState[row]) & (1 << index)) {/ / den senaste fysiskt knappen stat men den nuvarande fysiskt
knappläge skiljer sig från den nuvarande debounce
statliga...
om (buttonDebounceCounter [rad] [index] > 0 & &--buttonDebounceCounter [rad] [index] == 0) {/ / om den räknaren debounce har
varit minskas till 0 (menande den
knappen har varit upp i
kButtonUpDefaultDebounceCount
iterationer / / /

buttonEvent [rad] = 1 << index; köa en knapp staten change-händelse

om (buttonCurrent [rad] & (1 << index)) {/ / och växla knapparna debounce staten.
buttonState [rad] | = (1 << index);
}
annat {
buttonState [rad] & = ~ (1 << index);
}
}
}
}

{Ogiltig shift()

för (jag = 0; jag < 4; i ++) {

buttonLast [i] = buttonCurrent [i];

byte dataToSend = (1 << (jag + 4)) | (15 & ~ ledData[i]);

ställa in spärren pin låg så lysdioderna inte ändra samtidigt skickas i bitar
PORTD & = B10111111; //digitalWrite (ledLatchPin, låg);
flytta ut bitarna av dataToSend
shiftOut (ledDataPin, ledClockPin, LSBFIRST, dataToSend);
för (j = 0; j < 8; j ++) {
PORTD & = B11011111;//digitalWrite(ledClockPin,LOW);
digitalWrite (ledDataPin, ((dataToSend >> j) & 1));
om ((dataToSend >> j) & 1) {
PORTD| = B10000000;
}
annat {
PORTD & = B01111111;
}
PORTD|=B00100000;//digitalWrite(ledClockPin,High);
}
ställa in spärren pin hög så lysdioderna kommer att få nya uppgifter
PORTD| = B01000000; //digitalWrite (ledLatchPin, hög);

Avmattningen sätts i här slösa bort lite tid medan vi väntar på statligt av produktionen
Pins sedimentera. Utan denna tid slösa slinga, skulle en enda knapptryckning dyka upp som
två pressar (knappen och dess granne)
flyktiga int avmattning = 0;

medan (avmattning < 15)
{
Avmattningen ++;
}

När en rad har ställts in hög, ta emot data från knappar
ställa in spärren pin hög
PORTD| = B00010000; //digitalWrite (buttonLatchPin, hög);
skifta i data
buttonCurrent [i] = shiftIn (buttonDataPin, buttonClockPin, LSBFIRST) >> 3.
för (j = 0; j < 4; j ++) {
PORTD & = B11110111;//digitalWrite(buttonClockPin,LOW);
PORTD|=B00001000;//digitalWrite(buttonClockPin,High);
}
för (j = 0; j < 4; j ++) {
PORTD & = B11110111;//digitalWrite(buttonClockPin,LOW);
om ((PIND >> 2) & 1){//digitalRead(buttonDataPin)
buttonCurrent [i] | = 1 << j;
}
annat {
buttonCurrent [i] & = ~ (1 << j);
}
PORTD|=B00001000;//digitalWrite(buttonClockPin,High);
}
latchpin låg
PORTD & = B11101111; //digitalWrite (buttonLatchPin, låg);

för (k = 0; k < 4; k ++) {
buttonCheck(i,k);
}
}

stänga av lysdioder - detta sätt en rad inte visas ljusare än resten

ställa in spärren pin låg så lysdioderna inte ändra samtidigt skickas i bitar
PORTD & = B10111111; //digitalWrite (ledLatchPin, låg);
flytta ut 0
shiftOut (ledDataPin, ledClockPin, LSBFIRST, 0);
för (j = 0; j < 8; j ++) {
PORTD & = B11011111;//digitalWrite(ledClockPin,LOW);
PORTD & = B01111111;
PORTD|=B00100000;//digitalWrite(ledClockPin,High);
}
ställa in spärren pin hög så lysdioderna kommer att få nya uppgifter
PORTD| = B01000000; //digitalWrite (ledLatchPin, hög);
}

void checkFirstButton() {
för (byte en = 0; en < 4; a ++) {
om (buttonEvent[a]) {
för (byte b = 0; b < 4; b ++) {
om (buttonState [a] & (1 << b)) {
Växla firstPress variabel
firstPress = 0;
Visa nertryckta pixel
ledData [a] = buttonEvent [a];
lagra aktuell position
yPosition = a;
xPosition = 1 << b;
Återställ timers
timeX = 0;
timeY = 0;
hemkomst.
}
}
}
}
}

byte scaleAcc (int RAW) {
om (RAW < = 10 & & RAW > =-10) {
returnera 5.
}
annars om (RAW < -10) {
om (RAW < -50) {
Return 0;
}
annars om (RAW < -40) {
tillbaka 1.
}
annars om (RAW < -30) {
returnera 2.
}
annars om (RAW < -20) {
returnera 3.
}
annat {
returnera 4.
}
}
annars om (RAW > 10) {
om (RAW > 50) {
returnera 10.
}
annars om (RAW > 40) {
returnera 9.
}
annars om (RAW > 30) {
returnera 8.
}
annars om (RAW > 20) {
returnera 7.
}
annat {
returnera 6.
}
}
}

void checkAccelerometer() {
Läs värden
xGyroRAW = analogRead(A1);
yGyroRAW = analogRead(A0);
xAccRAW = analogRead(A4);
yAccRAW = analogRead(A3);
zAccRAW = analogRead(A2);

offset data
xGyroRAW = 317-xGyroRAW;
yGyroRAW = 183-yGyroRAW;
xAccRAW = 282-xAccRAW;
yAccRAW = 282-yAccRAW;
zAccRAW = 282-zAccRAW;

om (xAccRAW > 0) {
dirX = 1;
}
annat {
dirX = 0;
}
om (yAccRAW > 0) {
dirY = 1;
}
annat {
dirY = 0;
}

konvertera till 0-10
xAcc = scaleAcc(xAccRAW);
yAcc = scaleAcc(yAccRAW);
}

int getTime (byte acceleration) {
Växla (acceleration) {
fall 0: / / max - acceleration
returnera 25.
bryta;
fall 1:
returnera 25.
bryta;
fall 2:
gå tillbaka 50;
bryta;
fall 3:
gå tillbaka 100.
bryta;
fall 4:
returnera 150;
bryta;
fall 5: / / ligger platt
Return 0;
bryta;
fall 6:
returnera 150;
bryta;
fall 7:
gå tillbaka 100.
bryta;
mål 8:
gå tillbaka 50;
bryta;
mål 9:
returnera 25.
bryta;
mål 10: / / max + acceleration
returnera 25.
bryta;
}
}

void moveXPixel (int timeComp) {
om (timeComp == 0) {
}
annat {
om (timeX > timeComp) {
timeX = 0;
om (dirX) {
om (xPosition == 8) {
}
annat {
xPosition = xPosition << 1;
}
}
annat {
om (xPosition == 1) {
}
annat {
xPosition = xPosition >> 1;
}
}
}
}
}

void moveYPixel (int timeComp) {
om (timeComp == 0) {
}
annat {
om (timeY > timeComp) {
timeY = 0;
om (dirY) {
om (yPosition == 3) {
}
annat {
yPosition = yPosition + = 1;
}
}
annat {
om (yPosition == 0) {
}
annat {
yPosition = yPosition-= 1;
}
}
}
}
}

void checkMIDI() {
konvertera xPosition till decimal
växel (xPosition) {
fall 1:
AktuelltX = 0;
bryta;
fall 2:
AktuelltX = 1;
bryta;
fall 4:
AktuelltX = 2;
bryta;
mål 8:
AktuelltX = 3;
bryta;
}
om pixel har flyttat skicka midi
om (lastX! = AktuelltX || lastY! = yPosition) {
MIDImessage (noteON, (lastX + 5 * lastY + MIDIoffset), 0), //turn av sista anmärkning
MIDImessage (noteON, (AktuelltX + 5 * yPosition + MIDIoffset), velocity); //turn på nästa anteckning
}
lastX = AktuelltX;
lastY = yPosition;
}

void MIDImessage (int befalla, int MIDInote, int MIDIvelocity) {//send s ett MIDI-meddelande
Serial.write (kommandot); //send på eller av kommandot
Serial.write (MIDInote); //send pitch data
Serial.write (MIDIvelocity); //send hastighet data
}

void loop() {
om (firstPress) {
checkFirstButton();
}
annat {
för (byte pixel = 0; pixel < 4; pixel ++) {
om (pixel == yPosition) {
ledData [pixlar] = xPosition;
}
annat {
ledData [pixlar] = 0;
}
}
checkAccelerometer();
moveXPixel(getTime(xAcc));
moveYPixel(getTime(yAcc));
checkMIDI();
}
}

fyra pixlar studsande (använder bara x accelerometer, använder x gyro att rensa pixlar):

Accelerometer test-bounce
Amanda Ghassaei 2012

/*
* Detta program är fri programvara; Du kan vidaredistribuera det och/eller ändra
* det enligt villkoren i GNU General Public License som offentliggjorts av
* den Free Software Foundation; antingen version 2 av licensen, eller
* (på ditt alternativ) någon senare version.
*
*/

PIN-anslutningar
#define ledLatchPin 6
#define ledClockPin 5
#define ledDataPin 7
#define buttonLatchPin 4
#define buttonClockPin 3
#define buttonDataPin 2

installationsprogrammet för varibles för gyroskop/Accelerometer
int xGyroRAW;
int yGyroRAW;
int xAccRAW;
int yAccRAW;
int zAccRAW;

byte xGyro;
byte yGyro;
byte xAcc;
byte yAcc;
byte zAcc;

looping variabler
byte i.
byte j;
byte k;

lagring för ledde staterna, 4 byte
byte ledData [] = {0, 0, 0, 0};
lagring för knappar, 4 byte
byte buttonCurrent [] = {0,0,0,0}.
byte buttonLast [] = {0,0,0,0}.
byte buttonEvent [] = {0,0,0,0}.
byte buttonState [] = {0,0,0,0}.
knappen Dämpningstid counter - 16 byte
byte buttonDebounceCounter [4] [4].

variabler för accelerometer pixel rörelse
booleska firstPress [] = {0, 0, 0, 0};
byte movingPixel [] = {0, 0, 0, 0};
byte xPosition [4].
int timeX [] = {0, 0, 0, 0};
booleska dirX;
booleska dirY;
booleska prevDirX = 0;
booleska bounceDirection [] = {0, 0, 0, 0};
Boolean växla [] = {1, 1, 1, 1};
byte peakHeight [4].
byte lastX = 4;
byte lastY = 4;

MIDI-variabler
int hastighet = 100;
int noteON = 144;
int MIDIoffset = 60.
byte AktuelltX;
byte Observera [] = {60, 64, 67, 72};

void setup() {

DDRD = 0xFA; //set stift D7-D4 som D2 som indata-utdata

Serial.BEGIN (31250); //MIDI överföringshastighet

(CLI); //stop avbrott

Ställ in timer1 avbrott vid 1kHz
TCCR1A = 0; / / Ställ in hela TCCR1A register till 0
TCCR1B = 0; / / samma för TCCR1B
TCNT1 = 0, //initialize counter värde till 0.
ställa in timer räknas 1khz steg
OCR1A = 1999. / / = (16 * 10 ^ 6) / (1000 * 8) - 1
Aktivera CTC läge
TCCR1B | = (1 << WGM12);
Ange CS11 bit för 8 prescaler
TCCR1B | = (1 << CS11);
Aktivera timern jämför avbrott
TIMSK1 | = (1 << OCIE1A);

SEI (); //allow avbrott

}

ISR(TIMER1_COMPA_vect) {//Interrupt på freq 1 kHz
för (byte en = 0; en < 4; a ++) {
timeX [a] ++; //increment varje beståndsdel av timeX
}
Shift();
}

buttonCheck - kontrollerar status för en viss knapp.
denna buttoncheck funktion är i stort sett kopierade från monome 40h firmware brian crabtree och joe sjö
void buttonCheck (byte rad, byte index)
{
om (((buttonCurrent [rad] ^ buttonLast[row]) & (1 << index)) & & / / om det aktuella fysiska knapp läget skiljer sig från den
((buttonCurrent [rad] ^ buttonState[row]) & (1 << index))) {/ / last fysisk knapp staten och nuvarande debounced staten

om (buttonCurrent [rad] & (1 << index)) {/ / om nuläget fysisk knapp trycks
buttonEvent [rad] = 1 << index; köa upp en ny knapp händelse omedelbart
buttonState [rad] | = (1 << index); och ställa in debounced ner.
}
annat {
buttonDebounceCounter [rad] [index] = 12.
} / / annars knappen tidigare var deprimerad och nu
har släppts så vi våra debounce counter.
}
annars om (((buttonCurrent [rad] ^ buttonLast[row]) & (1 << index)) == 0 & & / / om det aktuella fysiska knapp läget är samma som
(buttonCurrent [rad] ^ buttonState[row]) & (1 << index)) {/ / den senaste fysiskt knappen stat men den nuvarande fysiskt
knappläge skiljer sig från den nuvarande debounce
statliga...
om (buttonDebounceCounter [rad] [index] > 0 & &--buttonDebounceCounter [rad] [index] == 0) {/ / om den räknaren debounce har
varit minskas till 0 (menande den
knappen har varit upp i
kButtonUpDefaultDebounceCount
iterationer / / /

buttonEvent [rad] = 1 << index; köa en knapp staten change-händelse

om (buttonCurrent [rad] & (1 << index)) {/ / och växla knapparna debounce staten.
buttonState [rad] | = (1 << index);
}
annat {
buttonState [rad] & = ~ (1 << index);
}
}
}
}

{Ogiltig shift()

för (jag = 0; jag < 4; i ++) {

buttonLast [i] = buttonCurrent [i];

byte dataToSend = (1 << (jag + 4)) | (15 & ~ ledData[i]);

ställa in spärren pin låg så lysdioderna inte ändra samtidigt skickas i bitar
PORTD & = B10111111; //digitalWrite (ledLatchPin, låg);
flytta ut bitarna av dataToSend
shiftOut (ledDataPin, ledClockPin, LSBFIRST, dataToSend);
för (j = 0; j < 8; j ++) {
PORTD & = B11011111;//digitalWrite(ledClockPin,LOW);
digitalWrite (ledDataPin, ((dataToSend >> j) & 1));
om ((dataToSend >> j) & 1) {
PORTD| = B10000000;
}
annat {
PORTD & = B01111111;
}
PORTD|=B00100000;//digitalWrite(ledClockPin,High);
}
ställa in spärren pin hög så lysdioderna kommer att få nya uppgifter
PORTD| = B01000000; //digitalWrite (ledLatchPin, hög);

Avmattningen sätts i här slösa bort lite tid medan vi väntar på statligt av produktionen
Pins sedimentera. Utan denna tid slösa slinga, skulle en enda knapptryckning dyka upp som
två pressar (knappen och dess granne)
flyktiga int avmattning = 0;

medan (avmattning < 15)
{
Avmattningen ++;
}

När en rad har ställts in hög, ta emot data från knappar
ställa in spärren pin hög
PORTD| = B00010000; //digitalWrite (buttonLatchPin, hög);
skifta i data
buttonCurrent [i] = shiftIn (buttonDataPin, buttonClockPin, LSBFIRST) >> 3.
för (j = 0; j < 4; j ++) {
PORTD & = B11110111;//digitalWrite(buttonClockPin,LOW);
PORTD|=B00001000;//digitalWrite(buttonClockPin,High);
}
för (j = 0; j < 4; j ++) {
PORTD & = B11110111;//digitalWrite(buttonClockPin,LOW);
om ((PIND >> 2) & 1){//digitalRead(buttonDataPin)
buttonCurrent [i] | = 1 << j;
}
annat {
buttonCurrent [i] & = ~ (1 << j);
}
PORTD|=B00001000;//digitalWrite(buttonClockPin,High);
}
latchpin låg
PORTD & = B11101111; //digitalWrite (buttonLatchPin, låg);

för (k = 0; k < 4; k ++) {
buttonCheck(i,k);
}
}

stänga av lysdioder - detta sätt en rad inte visas ljusare än resten

ställa in spärren pin låg så lysdioderna inte ändra samtidigt skickas i bitar
PORTD & = B10111111; //digitalWrite (ledLatchPin, låg);
flytta ut 0
shiftOut (ledDataPin, ledClockPin, LSBFIRST, 0);
för (j = 0; j < 8; j ++) {
PORTD & = B11011111;//digitalWrite(ledClockPin,LOW);
PORTD & = B01111111;
PORTD|=B00100000;//digitalWrite(ledClockPin,High);
}
ställa in spärren pin hög så lysdioderna kommer att få nya uppgifter
PORTD| = B01000000; //digitalWrite (ledLatchPin, hög);
}

void checkPress(byte Y) {
om (buttonEvent[Y]) {
för (byte b = 0; b < 4; b ++) {
om (buttonState [Y] & (1 << b)) {
Växla firstPress variabel
firstPress [Y] = 1;
Visa nertryckta pixel
ledData [Y] = (1 << b);
lagra aktuell position
xPosition [Y] = (1 << b);
lagra topphöjden
peakHeight [Y] = (1 << b);
Återställ timers
timeX [Y] = 0;
hemkomst.
}
}
}
}

byte scaleAcc (int RAW) {
om (RAW < = 10 & & RAW > =-10) {
returnera 5.
}
annars om (RAW < -10) {
om (RAW < -50) {
Return 0;
}
annars om (RAW < -40) {
tillbaka 1.
}
annars om (RAW < -30) {
returnera 2.
}
annars om (RAW < -20) {
returnera 3.
}
annat {
returnera 4.
}
}
annars om (RAW > 10) {
om (RAW > 50) {
returnera 10.
}
annars om (RAW > 40) {
returnera 9.
}
annars om (RAW > 30) {
returnera 8.
}
annars om (RAW > 20) {
returnera 7.
}
annat {
returnera 6.
}
}
}

void checkAccelerometerGyro() {
Läs värden
xGyroRAW = analogRead(A1);
yGyroRAW = analogRead(A0);
xAccRAW = analogRead(A4);
yAccRAW = analogRead(A3);
zAccRAW = analogRead(A2);

offset data
xGyroRAW = 317-xGyroRAW;
yGyroRAW = 183-yGyroRAW;
xAccRAW = 282-xAccRAW;
yAccRAW = 282-yAccRAW;
zAccRAW = 282-zAccRAW;

konvertera till 0-10
xAcc = scaleAcc(xAccRAW);
yAcc = scaleAcc(yAccRAW);

om (xAccRAW > 5) {
dirX = 1;
}
annars om (xAccRAW < 5) {
dirX = 0;
}
om (yAccRAW > 5) {
dirY = 1;
}
annars om (yAccRAW > 5) {
dirY = 0;
}

}

int getTime (byte acceleration) {
Växla (acceleration) {
fall 0: / / max - acceleration
gå tillbaka 100.
bryta;
fall 1:
gå tillbaka 100.
bryta;
fall 2:
returnera 150;
bryta;
fall 3:
returnera 200.
bryta;
fall 4:
returnera 250;
bryta;
fall 5: / / ligger platt
Return 0;
bryta;
fall 6:
returnera 250;
bryta;
fall 7:
returnera 200.
bryta;
mål 8:
returnera 150;
bryta;
mål 9:
gå tillbaka 100.
bryta;
mål 10: / / max + acceleration
gå tillbaka 100.
bryta;
}
}

void moveXPixel (byte Y, int timeComp) {
om (timeComp == 0) {
}
annat {
om (timeX [Y] > timeComp) {
timeX [Y] = 0;
om (dirX) {
om (peakHeight [Y] == 8 & & xPosition[Y]==8) {
IF(Toggle[Y]) {
MIDImessage (noteON, Obs [Y], 0); //send midi
växla mellan [Y] = 0;
ledData [Y] = 0;
}
annat {
MIDImessage(noteON,note[Y],velocity);
växla mellan [Y] = 1;
}
}
annat {
växla mellan [Y] = 1;
om (xPosition[Y]==peakHeight[Y]) {//if på topp
bounceDirection [Y] = 1; //falling
MIDImessage (noteON, Obs [Y], 0); //turn anmärkning av
}
om (xPosition[Y]==8) {//if slår botten
bounceDirection [Y] = 0; //rising
MIDImessage (noteON, Obs [Y], velocity); //turn anteckning på
}
om (xPosition[Y]==1) {
bounceDirection [Y] = 1;
}
om (bounceDirection[Y]) {
xPosition [Y] = xPosition [Y] << 1;
}
annat {
xPosition [Y] = xPosition [Y] >> 1;
}
}
}
annat {
om (peakHeight [Y] == 1 & & xPosition[Y]==1) {
IF(Toggle[Y]) {
MIDImessage (noteON, Obs [Y], 0); //send midi
växla mellan [Y] = 0;
ledData [Y] = 0;
}
annat {
MIDImessage(noteON,note[Y],velocity);
växla mellan [Y] = 1;
}
}
annat {
växla mellan [Y] = 1;
om (xPosition[Y]==peakHeight[Y]) {//if på topp
bounceDirection [Y] = 0; //falling
MIDImessage (noteON, Obs [Y], 0); //turn anmärkning av
}
om (xPosition[Y]==8) {
bounceDirection [Y] = 0;
}
om (xPosition[Y]==1) {//if slår botten
bounceDirection [Y] = 1; //rising
MIDImessage (noteON, Obs [Y], velocity); //turn anteckning på
}
om (bounceDirection[Y]) {
xPosition [Y] = xPosition [Y] << 1;
}
annat {
xPosition [Y] = xPosition [Y] >> 1;
}
}
}
}
}
}

void shake2Clear() {
om (abs(xGyroRAW) > 300) {
för (byte en = 0; en < 4; a ++) {
firstPress [a] = 0;
ledData [a] = 0;
}
}
}

void MIDImessage (int befalla, int MIDInote, int MIDIvelocity) {//send s ett MIDI-meddelande
Serial.write (kommandot); //send på eller av kommandot
Serial.write (MIDInote); //send pitch data
Serial.write (MIDIvelocity); //send hastighet data
}

void loop() {
checkAccelerometerGyro();
shake2Clear();
för (byte kolumn = 0; kolumnen < 4; kolumn ++) {
checkPress(column);
om (firstPress[column]) {
moveXPixel (kolumn, getTime(xAcc));
om (toggle[column]) {
ledData [kolumn] = xPosition [kolumn].
}
}
}
}

Relaterade Ämnen

Använda LEGO Mindstorm RCX ljussensor med Arduino (Program med Visuino)

I detta Instructable kommer du lära dig att programmera Arduino kontroll, och hämta data från LEGO Mindstorm RCX ljussensor med hjälp av Visuino - en enkel att använda grafiska utvecklingsmiljön för Arduino.Observera att anteckningen på några av bild...

Genom att använda Pimoroni Display-O-Tron med arduino

pimoroni Display-O-Tron 3000 (shop.pimoroni.com) är inte bara en av de bästa displayen för Raspberry Pi pengar kan köpa, hårdvaran köra stöds väl på Arduino plattform... Följ guiden!Steg 1: Hårdvara pinut Dot3k är en 3 x 16 LCD med 3 RGB bakgrundsbel...

Använda playstation remote på pc med arduino

jag har varit begåvad en gamla playstation 1 avlägsna en dag och ville använda den på datorn och sedan köpt en adapter på ebay som var defekt. Så beslutat jag äntligen att göra min egen med en arduino duemilanove. Jag försökte först att använda använ...

DH11 Temperatur och luftfuktighetsgivare med Arduino

Detta är en Tutorial på hur man använder DH11 temperatur och luftfuktighetsgivare med Arduino.Steg 1: Titta på denna Video (detta är en fullständig handledning)Denna video visar det fullständiga förfarandet om hur du använder denna Sensor.Steg 2: Ins...

Helgen projektet klocka datum termometer och luftfuktighet med Arduino mega

killar, jag vill dela min helg projekt på att skapa en klocka med fukt och temperaturgivare,Det är med DHT11 sensor, RTC DS1307, LCD 16 x 2 och Arduino Mega 2560,Hålla läsning och lycka tillSteg 1: Förbered alla delar behövs... i detta experiment beh...

En trådlös Smart Home (var: hem simulator och larm med Arduino eller Atmega328 (Uppdaterad maj 2016))

Obs: det nu är en android bluetooth kontroll app ibble för detta projektObs: Även om det började som ett projekt simulera min närvaro i hemmet, det har vuxit till ett smart hem, därav titeln jag detta InstructableNär folk är på semester, eller ibland...

Använda Switcheroo slå på ljuset med din smartphone

Switcheroo är tänkt att styra små nuvarande, låg power DC-spänningar som de som vanligen används i små enheter. Koppla på en lampa är en hög ström, hög effekt AC spänning program. Det enklaste och säkraste sättet att byta dessa typer av saker med din...

Använda en USB-Barcode Scanner med en iPad

Du kan använda en USB-Barcode Scanner med en iPad men du måste få smart med olika tillbehör.Steg 1: Skaffa en powered "USB Camera Connection Kit" Du behöver en kamera eller media connection kit/adapter och i de flesta fall din kommer att vilja h...

Använda frys papper och en skrivare att göra ram-stånd konst (och en återanvändbar utskrivbara stämpel)

I detta instructable du lära dig att använda frysen papper och en injet skrivare att göra stämplat inked konst på tyg. Denna teknik fungerar särskilt bra med typografi och ser bra ut i tovigt ramar. Jag hittade detta särskilt tryck på Etsy. Jag fråga...

Kolla fuktighet, temperatur och daggpunkt med Arduino

Kolla fuktighet, temperatur och daggpunkt med Arduino uno med DHT11 Sensor genom seriella Monitor.Steg 1: DHT11 givare (luftfuktighet Sensor)Anslutning av tråd.Röd = VCC 5VGrön = Data stiftSvart = jordPIN-konfiguration:Röd = 5VGrön = stift 7Svart = j...

Använda Dragino han och mega328p för att bygga en likadan lösning för Arduino Yun

I detta projekt, kommer att vi göra en Arduino Yun både lösning med hjälp av Dragino HE.mega328p och andra komponenter.Här kommer vi bygga en Arduino Yun både solutiom och visar hur man programmerar mega328p via WiFi. och hur till demo kommunikation...

Hur man ladda ner och använda Spotify på en dator med Windows

detta instructable kommer att lära dig hur man ladda ner och använda programmet musik Spotify på en dator som kör windows. Spotify är en kommersiell musik streaming program som erbjuder ett brett utbud av stora och oberoende skivbolag till lyssnare....

Använda alternativa noll och justering lasrar med handibot

Det har kommit flera gånger i forum och G + att det verkar som en hel Handibot ägare inte förstår alla de sätt du kan manuellt indexera handibot så jag tänkte jag skulle göra lite instructable.Detta kan vara till hjälp för andra cnc router ägare ocks...

En svävar sfär roterar lyser och blinkar med Arduino

En svävar lite Dödsstjärnan i Instructables bjöd in mig till det nya projektet med Arduino. Tre principer var beslutat och höll för att skilja den från föregångaren.Gör det själv med någon (eller mindre) färdiga.Hålla roterande.Göra glöd och blinka u...

Mest använda Motor enheter och dess användningsområden

Motor enheter används ofta i varje projekt. Signalerna från mikrokontroller kan inte direkt styra DC eller stepper motors. Använda för att integrera signaler från att integrera drivrutinen för som styr motorn enligt dess nuvarande höja. Det gjorde så...

Använda XML på Raspberry Pi med Python

Detta Instructable kommer att diskutera användningen av XML på ansökningar om Raspberry Pi. Steg ett täcker vad är XML och formatet för datastrukturer. Steg två täcker bygga och parsning av XML i Python och steg tre kommer att visa hur XML används so...

Använda Si4703 FM Breakout styrelsen på Arduino Uno

i det här inlägget kommer jag demo hur man använder SI4703 FM Breakout styrelsen på Arduino UnoSi4703 FM-breakout styrelsen för Silicon Laboratories Si4703 FM tuner chip.Utöver att vara en enkel FM-radio, kan Si4703 också upptäcka och bearbeta både R...

Untethered taligenkänning och syntes med Arduino

MOVI står för "Min egen röst Interface" och är en kickstarter-backed Arduino Shield som gör det mycket enkelt att bygga din egen tal dialoger att styra enheter inom Arduino IDE. Denna snabba instructable visar dig hur du kommer igång att inrätta...

Taligenkänning och syntes med Arduino

I min tidigare Instructable visade jag hur man styr ett par lysdioder med en Arduino ombord och BitVoicer Server. I detta Instructable ska jag göra saker lite mer komplicerat. Jag kommer också att syntetisera tal med Arduino DUEdigital till analog om...