Hamsterloop (4 / 14 steg)

Steg 4: Bilen - övervakning och kontroll



Jag ville mäta accelerationen av bilen och även lufttrycket i bilen. Jag placerade en Arduino Nano i bilen med tryckgivare och acceleration sensor. Tillägg av en Bluetooth-modul får bilen systemet läsa och kontrolleras från utanför röret (via blå sikt Android app).

Från början hade jag Bluetooth-modulen ansluts via mjukvaran följetong. Detta orsakade vilda svängningar i den signal till fan controller stift, och vi brände ut ett par av elektronisk hastighet kontroller. Använder standard Serial stiften 0 och 1 så småningom löste detta problem, men kräver nu koppla bort Bluetooth när du laddar en uppdaterad skiss.

Lista över verktyg & komponenter

• Verktyg - se generella verktyg lista
• Komponenter
o Arduino Nano V3-Ebay $5
o 28 pin DIP Socket – Wide – (30 PIN-kod inte tillgänglig) Ebay $2
o Prototyping styrelsen – Ebay $3
o HC-06 Bluetooth slav modul – Ebay $7
o BMP180 barometrisk Sensormodul – Ebay $9
o MPU-6050 3 axel Gyro/Accel modul – Banggood Kina $3

Detta är den Arduino skiss används i bilen.

HyperloopCar
Version 02 Lägg accelerometer MPU6050
Version 03 lägga kanalanslutna fläkthastighetskontroll (servo lib)
Backa på SortwareSerial - bara använda stift 0 & 1
Version 04 Lägg gyro behandlingen och rulla calc för inställning av nätverksbelastning servo
04b gå tillbaka till SoftwareSerial
04c Lägg till timer för att stänga av fläkt efter x sekunder
Version 05 kommentar ut balansera servo kod, displayen tryck när det ändras
05b elim mjukvaran följetong eftersom det orsakade störningar på signal till ESC

#include "Servo.h" //lib för att köra fan & servo
#include "MPU6050.h" / / accel/gyro-sensor
#include "SoftwareSerial.h" //for BT anslutning till andra stift

#include "SFE_BMP180.h" / / temp.pressure sensor
#include "Wire.h" / / mindre än och större än-tecken vilse i
#include "I2Cdev.h" / / rå Instructables redaktör

Servo esc;
Servo servo;
int gaspådrag = 1300; standard. kan ställas in genom BT Seriell inmatning
#define runtime 15000 / / tid tills det stängs automatiskt
#define fanstop 700 / / mikrosekund pulse med för att stoppa fläkten
lång fanTime = 0; Hur lång fan har varit på

MPU6050 accelgyro; 0x68 är standardadressen I2C
knyta AD0 stift till 5v + ange 0x69
för beräkning av rulle
#define M_PI 3.14159265359
#define dt 0,01
#define gyroSens 65.536 //copied från web exempel??? verkar fungera

int16_t ax, ay, az;
int16_t gx, gy, gz;
int16_t ayMaxPlus, ayMaxMinus, axMax, azMax; Spara max värden
#define OUTPUT_READABLE_ACCELGYRO
#define cvtFtSec2 62 //conversion från rå till sq ft/SEK
#define OUTPUT_BINARY_ACCELGYRO
float rulle = 0;

SoftwareSerial mySerial (5, 6); RX, TX Objst för BT följetong

int ledPin = 2;
char state = 0;
int flagga = 0;
char stat; variabler för temp/tryck
T, P, p0, a;
float psi;
float temp = 0;
float savePressure;
char ctlChar = "0";

SFE_BMP180 tryck; objekt för temp/tryck sensor
#define höjd 137.0 / / Est höjd i meter
int pressureCtr = 0;
BMP-180 ledningar
Några Arduino stift märkt: SDA SCL 5 + Gnd
Uno, Redboard, Pro: A4 A5
Mega2560, Due: 20 21
Leonardo: 2 3

int serialCtr = 0; inte leta följetong / p varje gång genom loop

void setup() {

ESC.attach (9, fanstop, 2000); PIN-koden för elektronisk varvtalsreglering
för kanalanslutna fan, min microsec puls med, och max om du vill ange intervall
esc.writeMicroseconds(fanstop); inställt på

servo.attach(10); PIN-kod för att balansera servo

Wire.BEGIN(); behövs?

pinMode (ledPin, produktionen);
digitalWrite (ledPin, låg);

Serial.BEGIN(9600); Standard anslutningshastighet för min BT modul
Serial.println("HyperloopCar05b");

om (! pressure.begin()) {
Serial.println ("BMP180 init fail\n\n");
While(1); Paus för evigt.
}
Serial.println fick ("här");
accelgyro.Initialize();
accelgyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_16); ändra från 2g standardintervall
Kontrollera anslutning
Serial.println(accelgyro.testConnection()? "MPU6050 anslutning framgångsrika": "MPU6050 anslutning misslyckades");
Serial.Print ("0 -> 9 = max fläkt");
Serial.Print ("s = fan start o = fan av");
Serial.println ("p = tryck avläsningar jag = initiera ESC");
pinMode (13, OUTPUT);
digitalWrite 13, hög. allt är väl indikatorn

}

void loop() {
serialCtr ++;
om (serialCtr > 10) {; //check för förbrukaren insatsen ibland
checkInput();
serialCtr = 0;
}

om ((fanTime! = 0) & & (millis() - fanTime > runtime)) {
stopFan(); stänga av automatiskt
}

get info rom MPU6050, acceleration och gyro
accelgyro.getMotion6 (& ax, ay, az, & gx, & gy, & gz); få avläsningar från MPU6050
om (ay > 0 & & ay > ayMaxPlus) ayMaxPlus = ay; Spara fwd/bkwd accel raw värdet
om (ay < 0 & & ay < ayMaxMinus) ayMaxMinus = ay;

/ * calcRoll (ax, ay, az, gy, och rulle); calc rulle. passera en & g-värden och ptr att rulla
int degRoll = rulle * 100;
Serial.Print("degRoll="); Serial.println(degRoll);
Delay(100);
int servoangle = karta (degRoll, -50, 50, 60, 135); karta +-50deg vinkel till servo maxes
adj mappning till tune balans
om (abs (degRoll < 50)) {
Serial.Print("Angle="); Serial.println(servoangle);
servo.write(servoangle); flytta trim servo att hålla balansen
}
*/
pressureCtr ++;
om (pressureCtr > 100) {//only göra detta varje gång på ett tag
pressureCtr = 0;
checkPressure(); få aktuella psi & temp
Serial.Print("savePressure="); Serial.Print(savePressure);
Serial.Print ("psi ="); Serial.println(PSI);
om (abs(savePressure-psi) >.5) {
savePressure = psi;
dispReadings();
}
}
}

int ms;
void startFan() {//increase hastighet gradvis till max
fanTime = millis(); spara tid när vi slår på den
Serial.Print ("upp till"); Serial.Print(Throttle); Serial.Print ("max för");
Serial.Print(runtime / 1000); Serial.println ("sekunder");
för (ms = fanstop; ms < = gas; ms += 12) {
Serial.Print ("puls ms =");
Serial.println(MS);
esc.writeMicroseconds(ms);
Delay(125);
}
}

void stopFan() {
Serial.println ("stoppa fläkten");
för (ms = ms-100; ms > = fanstop; ms-= 25) {
Serial.Print ("puls ms =");
Serial.println(MS);
esc.writeMicroseconds(ms);
Delay(125);
}
fanTime = 0;
}

void checkInput() {
om (Serial.available() > 0) {/ / se om någon användare ingång
ctlChar = Serial.read();
Serial.println();
int jag = ctlChar - '0'; konvertera singe röding till heltal
om (jag > = 0 & & jag < = 9) {//set spjäll
gaspådrag = karta (i, 0, 9, 1300, 1800); variera bewteen låg & hög
Serial.Print ("max gas puls inställd på");
Serial.println(Throttle);
} else om (ctlChar == 's ") {
startFan();
} else om (ctlChar == ' o ') {
stopFan();
} else om (ctlChar == "p") {
dispReadings();
} else om (ctlChar == "i") {
initializeESC();
}
}
}
/*
void calcRoll (int16_t aax, int16_t aay, int16_t aaz, int16_t ggy, flyta * rulle) {
float rollAcc;
integrera gyro data, cvt vinkelhastighet till vinkel
* rulla-= ((float) ggy / gyroSens) * dt; vinkel
kompensera för drift wil accel data om giltigt
int forceMagnitudeApprox = abs(aax) + abs(aay) + abs(aaz);
om (forceMagnitudeApprox > 8192 * forceMagnitudeApprox < 32768) {
vrida runt den x & z axlar resultat i vektor på y-axeln
rollAcc = ARCTAN2 ((float) aax, (float) aaz) * 180 / M_PI;
* rulla = * roll * 0,98 + rollAcc * 0,02; jämna det i
}
}
*/

void initializeESC() {/ / "tåg" esc för att känna igen arduino spjäll
lång savTime = millis();
esc.writeMicroseconds(2000); set till max
Serial.println ("nu skicka max effekt till ESC");
Serial.println ("slå på strömmen till ESC, vänta 2 sek, och tryck på valfri tangent när du är klar");
tag (!. Serial.available()); vänta på ingång
Serial.Read();
Delay(2000); för > 2 sekunder
esc.writeMicroseconds(fanstop); ställa in till min
Serial.Print("...");
Delay(2000);
Serial.println("Done");
}

void dispReadings() {/ / diplay avläsningar på seriell enhet

Serial.Print ("ayMax ="); Serial.Print(ayMaxPlus / cvtFtSec2);
Serial.Print(""); Temp & Tryck
Serial.Print(temp);
Serial.Print "F".
Serial.Print(PSI,1);
Serial.println ("psi");
}

void checkPressure() {
stat = pressure.startTemperature();
om (stat! = 0)
{
Delay(stat); Vänta för mätning att slutföra:

Hämta den färdiga temperaturmätning:
Observera att mätningen har lagrats i variabeln T.
Returnerar 1 om det lyckas, 0 om misslyckande.

stat = pressure.getTemperature(T); Hämta färdiga temp
om (stat! = 0)
{
Starta en mätning:
Parametern är den oversampling inställningen, från 0 till 3 (högsta res, längsta väntan).
Om begäran är framgångsrika, returneras antalet ms att vänta.
Om begäran misslyckas returneras 0.

stat = pressure.startPressure(3);
om (stat! = 0)
{
Vänta för mätning att slutföra:
Delay(stat);
Temp = T; Fahrenheit visar det sig
Temp = (((9.0/5.0)*T)+32.0); behövs för Farenheit

Hämta den färdiga mätningen:
Observera att mätningen har lagrats i variabeln P.
Observera också att funktionen kräver föregående temperaturmätning (T).
(Om temperaturen är stabil, kan du göra en temperaturmätning för ett antal tryckmätningarna.)
Returnerar 1 om det lyckas, 0 om misslyckande.

stat = pressure.getPressure(P,T);
om (stat! = 0)
{
PSI = P * 0.014503773773;
}
annat Serial.println ("fel vid hämtning av trycket measurement\n");
}
annat Serial.println ("fel vid start av trycket measurement\n");
}
annat Serial.println ("fel vid hämtning av temperatur measurement\n");
}
annat Serial.println ("fel start temperatur measurement\n");
Delay(2000);
}

Se Steg
Relaterade Ämnen