Forum modelarskie RC , projektowanie CAD http://forum.aerodesignworks.eu/ |
|
DIY SkyAssistant http://forum.aerodesignworks.eu/viewtopic.php?f=31&t=1429 |
Strona 1 z 1 |
Autor: | dexter_ck [ 5 wrz 2016, o 23:05 ] |
Tytuł: | DIY SkyAssistant |
Witam wszystkich Po paru dniach męki z moim antytalentem do programowania udało mi się stworzyć coś na kształt wariometru akustycznego + zapisu parametrów lotu. W szufladzie zalegało już pare gratów, które można było dobrze zagospodarować, jedynie brakło czasu . Jednym z takich zalegających gratów był sterownik do gimbala. Wymagał wgrania bootloadera i zagospodarowaniu paru, wyprowadzonych już pinów. Równie dobrze można użyć zwykłego arduino nano (mi po prostu było szkoda ) Kolejnym elementem był czytnik kart microSD, BMP 180 oraz nadajnik + odbiornik RF. Po wyprowadzeniu pinów SPI oraz wlutowaniu BMP 180 wyglądało to tak: Załącznik: Załącznik: Generalnie u mnie będzie to służyć razem z FPV (mam wolną linie akurat od dźwięku), ale nie każdy ma ochotę wydawać góry pieniędzy więc sprzęt został przetestowany na najprostszym nadajniku radiowym + buzzer. Załącznik: Załącznik: No i finalnie wygląda to tak: Kod dla vario znaleziony tutaj: http://www.rcgroups.com/forums/showthre ... 08&page=31 W skrócie: Potrzebujemy: -Arduino Nano (albo coś innego na ATmedze ) (ok 15zł) -Buzzer (1zł) -Rezystory, kondensatory, kabelki, lutownica, potencjometr (do regulowania głośności na ziemi) etc. (ok. 3zł) -Nadajnik/odbiornik RF (ok. 5zł) -Czytnik kard SD (jeżeli nie chcemy mieć takiego wypasu, po prostu ściągamy szkic z RCG i wgrywamy na Arduino) (ok. 5zł) -Zasilanie 5V -BMP180 lub BMP085 (dla lepszej jakości można kupić MS5611) (ok. 14zł) -KartaSD (ok.15zł) -minimum umiejętności manualnych Łącznie: ok. 43zł Dla przykładu SkyAssistant PitLaba kosztuje 700zł, chociaż możliwościami na pewno przewyższa wielokrotnie Co otrzymujemy: -Dane o wysokości, temperaturze i ciśnieniu -Akustyczny wariometr -Za pomocą Microsoft Office z pliku .txt otrzymujemy wykresy (tutaj akurat spacer po domu, BMP180 nie jest super dokładny) Załącznik: Szkic dla Arduino: Kod: // Temperaturra w *C, Ciśnienie w Pa, wysokość QFE w m #include <Wire.h> #include <Adafruit_BMP085.h> #include <SPI.h> #include <SD.h> const int chipSelect = A2; Adafruit_BMP085 bmp; // nazwa BMP, odnośnik float base; float QFE; float alt1; float alt2; const byte led = 13; unsigned long time = 0; float toneFreq, toneFreqLowpass, flpressure, lowpassFast, lowpassSlow ; float p0; // this will be used to store the airfield elevation pressure int altitude; int ch1; // Here's where we'll keep our channel values int ddsAcc; #define I2C_ADDRESS 0x77 const unsigned char oversampling_setting = 3; //oversamplig for measurement const unsigned char pressure_waittime[4] = { 5, 8, 14, 26 }; //Sensor parameters taken from the BMP085 datasheet int ac1, ac2, ac3; unsigned int ac4, ac5, ac6; int b1, b2, mb, mc, md; int temperature; long pressure; void setup() { Serial.begin(9600); pinMode (led, OUTPUT); bmp.begin(); // uruchomienie BMP Serial.print("Initializing SD card..."); // see if the card is present and can be initialized: if (!SD.begin(chipSelect)) { Serial.println("Card failed, or not present"); // don't do anything more: return; } Serial.println("card initialized."); base = bmp.readAltitude(); Serial.println("Setting up BMP085"); Wire.begin(); bmp085_get_cal_data(); bmp085_read_temperature_and_pressure(&temperature,&pressure); flpressure=pressure;// move long type pressure into float type flpressure p0 = lowpassFast = lowpassSlow = flpressure; Serial.print(" p0 = "); Serial.println(p0); pinMode(3, INPUT); // Set our input pins as such for altitude command input from receiver via pin D3 } void loop() { ////////////////////SD + serial QFE = (float)bmp.readAltitude() - (float) base ; // pomiar wysokości nad miejscem startu Serial.println(); Serial.print(bmp.readTemperature()); Serial.print(","); Serial.print(bmp.readPressure()); Serial.print(","); Serial.print(QFE); File dataFile = SD.open("datalog.txt", FILE_WRITE); if (dataFile) { dataFile.println(); dataFile.print(bmp.readTemperature()); dataFile.print(","); dataFile.print(bmp.readPressure()); dataFile.print(","); dataFile.print(QFE); dataFile.close(); } // if the file isn't open, pop up an error: else { Serial.println("error opening datalog.txt"); } bmp085_read_temperature_and_pressure(&temperature,&pressure); // Serial.print(temperature,DEC); // Serial.print(" "); // Serial.print(pressure,DEC); // Serial.print(" "); flpressure = pressure;// move long type pressure into float type flpressure altitude = (float)44330 * (1 - pow(((float) flpressure/p0), 0.190295)); // Serial.print(" "); // Serial.println(altitude); lowpassFast = lowpassFast + (flpressure - lowpassFast) * 0.3; lowpassSlow = lowpassSlow + (flpressure - lowpassSlow) * 0.15; toneFreq = (lowpassSlow - lowpassFast) * 50; toneFreqLowpass = toneFreqLowpass + (toneFreq - toneFreqLowpass) * 0.1; toneFreq = constrain(toneFreqLowpass, -1000, 1000); ddsAcc += toneFreq * 100 + 2000; if (toneFreq < 100 || ddsAcc > 0) { tone(A1, toneFreq + 510); ledOn(); // the Arduino led will blink if the Vario plays a tone, so you can test without having audio connected } else { noTone(A1); ledOff(); } while (millis() < time); //loop frequency timer time += 20; int ones = altitude%10; int tens = (altitude/10)%10; int hundreds = (altitude/100)%10; int thousands = (altitude/1000)%10; // Serial.print ("thousands: "); // Serial.println (thousands); // Serial.print ("hundreds: "); // Serial.println (hundreds); // Serial.print ("tens: "); // Serial.println (tens); // Serial.print ("ones: "); // Serial.println (ones); ch1 = pulseIn(3, HIGH, 25000); // Read the pulse width of servo signal connected to pin D3 // Serial.print (ch1); // // if(ch1>1000){ // Serial.println("Left Switch: Engaged"); // } // if(ch1<1000){ // Serial.println("Left Switch: Disengaged"); // } if((map(ch1, 1000,2000,-500,500)) > 0) // interpret the servo channel pulse, if the Vario should beep altitude or send vario sound { noTone(A1); // create 750 ms of silence, or you won't hear the first altitude beep ledOff(); delay(750); if(hundreds == 0) { tone(A1,900); //long duration tone if the number is zero ledOn(); delay(600); noTone(A1); ledOff(); } else for(char a = 0; a < hundreds; a++) //this loop makes a beep for each hundred meters altitude { tone(A1,900); // 900 Hz tone frequency for the hundreds ledOn(); delay(200); noTone(A1); ledOff(); delay(200); } delay(750); //longer delay between hundreds and tens if(tens == 0) { tone(A1,1100); //long pulse if the number is zero ledOn(); delay(600); noTone(A1); ledOff(); } else for(char a = 0; a < tens; a++) //this loop makes a beep for each ten meters altitude { tone(A1,1100); //1100 Hz tone frequency for the tens ledOn(); delay(200); noTone(A1); ledOff(); delay(200); } for (int p0=0; p0 <= 20; p0++) { // warming up the sensor again, by reading it 20 times bmp085_read_temperature_and_pressure(&temperature,&pressure); } } } void bmp085_read_temperature_and_pressure(int* temperature, long* pressure) { int ut= bmp085_read_ut(); long up = bmp085_read_up(); long x1, x2, x3, b3, b5, b6, p; unsigned long b4, b7; //calculate the temperature x1 = ((long)ut - ac6) * ac5 >> 15; x2 = ((long) mc << 11) / (x1 + md); b5 = x1 + x2; *temperature = (b5 + 8) >> 4; //calculate the pressure b6 = b5 - 4000; x1 = (b2 * (b6 * b6 >> 12)) >> 11; x2 = ac2 * b6 >> 11; x3 = x1 + x2; if (oversampling_setting == 3) b3 = ((int32_t) ac1 * 4 + x3 + 2) << 1; if (oversampling_setting == 2) b3 = ((int32_t) ac1 * 4 + x3 + 2); if (oversampling_setting == 1) b3 = ((int32_t) ac1 * 4 + x3 + 2) >> 1; if (oversampling_setting == 0) b3 = ((int32_t) ac1 * 4 + x3 + 2) >> 2; x1 = ac3 * b6 >> 13; x2 = (b1 * (b6 * b6 >> 12)) >> 16; x3 = ((x1 + x2) + 2) >> 2; b4 = (ac4 * (uint32_t) (x3 + 32768)) >> 15; b7 = ((uint32_t) up - b3) * (50000 >> oversampling_setting); p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2; x1 = (p >> 8) * (p >> 8); x1 = (x1 * 3038) >> 16; x2 = (-7357 * p) >> 16; *pressure = p + ((x1 + x2 + 3791) >> 4); } unsigned int bmp085_read_ut() { write_register(0xf4,0x2e); delay(5); //longer than 4.5 ms return read_int_register(0xf6); } void bmp085_get_cal_data() { Serial.println("Reading Calibration Data"); ac1 = read_int_register(0xAA); Serial.print("AC1: "); Serial.println(ac1,DEC); ac2 = read_int_register(0xAC); Serial.print("AC2: "); Serial.println(ac2,DEC); ac3 = read_int_register(0xAE); Serial.print("AC3: "); Serial.println(ac3,DEC); ac4 = read_int_register(0xB0); Serial.print("AC4: "); Serial.println(ac4,DEC); ac5 = read_int_register(0xB2); Serial.print("AC5: "); Serial.println(ac5,DEC); ac6 = read_int_register(0xB4); Serial.print("AC6: "); Serial.println(ac6,DEC); b1 = read_int_register(0xB6); Serial.print("B1: "); Serial.println(b1,DEC); b2 = read_int_register(0xB8); Serial.print("B2: "); Serial.println(b2,DEC); mb = read_int_register(0xBA); Serial.print("MB: "); Serial.println(mb,DEC); mc = read_int_register(0xBC); Serial.print("MC: "); Serial.println(mc,DEC); md = read_int_register(0xBE); Serial.print("MD: "); Serial.println(md,DEC); } long bmp085_read_up() { write_register(0xf4,0x34+(oversampling_setting<<6)); delay(pressure_waittime[oversampling_setting]); unsigned char msb, lsb, xlsb; Wire.beginTransmission(I2C_ADDRESS); Wire.write(0xf6); // register to read Wire.endTransmission(); Wire.requestFrom(I2C_ADDRESS, 3); // read a byte while(!Wire.available()) { // waiting } msb = Wire.read(); while(!Wire.available()) { // waiting } lsb |= Wire.read(); while(!Wire.available()) { // waiting } xlsb |= Wire.read(); return (((long)msb<<16) | ((long)lsb<<8) | ((long)xlsb)) >>(8-oversampling_setting); } void write_register(unsigned char r, unsigned char v) { Wire.beginTransmission(I2C_ADDRESS); Wire.write(r); Wire.write(v); Wire.endTransmission(); } char read_register(unsigned char r) { unsigned char v; Wire.beginTransmission(I2C_ADDRESS); Wire.write(r); // register to read Wire.endTransmission(); Wire.requestFrom(I2C_ADDRESS, 1); // read a byte while(!Wire.available()) { // waiting } v = Wire.read(); return v; } int read_int_register(unsigned char r) { unsigned char msb, lsb; Wire.beginTransmission(I2C_ADDRESS); Wire.write(r); // register to read Wire.endTransmission(); Wire.requestFrom(I2C_ADDRESS, 2); // read a byte while(!Wire.available()) { // waiting } msb = Wire.read(); while(!Wire.available()) { // waiting } lsb = Wire.read(); return (((int)msb<<8) | ((int)lsb)); } void ledOn() { digitalWrite(led,1); } void ledOff() { digitalWrite(led,0); } Oczywiście zachęcam do modyfikowania kodu, dodawania swoich pomysłów i sugestii itp. |
Autor: | mgr [ 11 wrz 2016, o 19:28 ] |
Tytuł: | Re: DIY SkyAssistant |
Dobra robota Przydał by Ci się jeszcze jakiś program do rysowania tych wykresów, bo ten excel to tak sobie . W C# jest kontrolka do wykresów, można za jej pomocą bez większego wysiłku stworzyć coś ciekawego |
Strona 1 z 1 | Strefa czasowa UTC+2godz. |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |