hornet20 Opublikowano 18 Listopada 2016 Opublikowano 18 Listopada 2016 Witajcie, Wiele osob pyta mnie o zabawki, ktore uzywam w DLG zrobione na arduino. Nie jestem programista, ani elektronikiem, wiec jest wiele bledow. Najważniejsze jednak, że dziala Jest wiele watkow opisujacych jak zaczac zabawe z arduino (instalujemy srodowisko arduino, sterowniki, dodawanie bibliotek...), dlatego ta czesc pomine. Jako pirwsze opisze prosty i bardzo tani logger wysokosci. Lista zakupow z Chin: 1) plytka arduino pro mini (1,25$ ) https://www.arduino.cc/en/Main/ArduinoBoardProMini 1a) dodatkowo do zaprogramowania konieczny bedzie programator na ukladzie FTDI232 (1,20$) - doslownie nie jest to programator a emulator portu RS232 na USB, z wyjsciem TTL. 2)plyteczka z portem karty microSD, w wersji zasilanej oraz sterowanej napieciem 5V - (ok 0,50$) https://s15.postimg.org/kfxyhv23f/microsd_breakout_board.jpg 3) czujnik cisnienia BMP180 (np shield GY-68) wazne aby byl sterowany poziomem 5v - (2,50$) 4) kabelek od serwomechanizmu (z szuflady 0$). Ceny z aliekspress przy opcji FREE SHIPPING. Podsumowując 4,25$ bez programatora (po dzisiejszym kursie to nie cale 19zl). No i zaczynamy. Oczywiscie nie lutujemy goldpinow, tylko cienkimi przewodami laczymy plytki na pajaka i skladamy kanapeczke. Oto schemat: a oto moj "pajaczek": Wymiary 40x20x10mm, waga 9g. No i zostaje wgranie programu. Zaprezentowany przeze mnie kod jest troszke przemodelowanym zlepkiem przykladow arduino (pomiar wysokosci i zapis na SD), zaprezentowany kiedys tu: http://jadiema.blogspot.com/2014/09/micro-rocket-data-logger.html W moim kodzie dodalem filtr dolnoprzepustowy, oraz logowanie poziomu PWM na kanale odbiornika w ktorym bedzie wpiety logger. /* SD card datalogger This example shows how to log data from three analog sensors to an SD card using the SD library. The circuit: * analog sensors on analog ins 0, 1, and 2 * SD card attached to SPI bus as follows: ** MOSI - pin 11 ** MISO - pin 12 ** CLK - pin 13 ** CS - pin 4 Pins SDA & SCL BMP085 wiring ** SDA - A4 ** SCL - A5 ** VCC - 5V ** GND - GND Pin to receiver channel ** pin 9 */ #include <Wire.h> #include <SD.h> #define PWMpin 9 #define DEBUG //#define DEBUG_BMP085 int tempomesure = 500; //temporisation de la boucle unsigned long t0=0; unsigned long prevMillis=0; //BMP085 #define BMP085_ADDRESS 0x77 // I2C address of BMP085, idem BMP1080 const unsigned char OSS = 0; // Oversampling Setting // Calibration values int ac1; int ac2; int ac3; unsigned int ac4; unsigned int ac5; unsigned int ac6; int b1; int b2; int mb; int mc; int md; // b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...) // so ...Temperature(...) must be called before ...Pressure(...). long b5; short temperature; long pressure; // Use these for altitude conversions const float p0 = 101325; // Pressure at sea level (Pa) float altitude; //LOW PASS FILTER float LowPassAltitude; //Reveiver channel int PWMval =0; //SD CARD const int chipSelect = 4; long fileNum = 0; // maximum 99999 String fileName; char name[13]; File dataFile; void incFileNum() { // generate next file name: String s = "dat" + String(++fileNum) + ".txt"; s.toCharArray(name,13); } void save(String s) { dataFile = SD.open(name, FILE_WRITE); if (dataFile) { dataFile.println(s); dataFile.close(); Serial.println(s); } else Serial.println("error opening " + String(name)); } void setup() { pinMode(chipSelect, OUTPUT); // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } Serial.print("Initializing SD card..."); // make sure that the default chip select pin is set to // output, even if you don't use it: // 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."); //Efface le fichier initial // SD.remove("DATA.txt"); //GESTION DES NOMS DES FICHIERS //-------------------------------------------------- incFileNum(); // set it to datxxxx.txt while (SD.exists(name)) incFileNum(); #ifdef DEBUG Serial.println("new file name: " + String(name)); #endif //-------------------------------------------------- save("t(ms),Altitude(m)*100,LowPassAltitude(m)*100,Pression(Pa),Temperature(C)*10,PWM"); //CAPTEUR bmp085 Wire.begin(); bmp085Calibration(); //initialisation du temps: unsigned long prevMillis = millis(); pinMode(PWMpin,INPUT); // reveiver channel PWM //first measure temperature = bmp085GetTemperature(bmp085ReadUT()); pressure = bmp085GetPressure(bmp085ReadUP()); altitude = (float)44330 * (1 - pow(((float) pressure/p0), 0.190295)); LowPassAltitude=altitude; } void loop() { if ((millis() - prevMillis) > tempomesure) { /////////////////////////////////////////////////////////////// PWMval = pulseIn(9,HIGH); // PWMval=map(PWMval, 0, 1028, 0, 255); // Capteur pression et temperature temperature = bmp085GetTemperature(bmp085ReadUT()); pressure = bmp085GetPressure(bmp085ReadUP()); altitude = (float)44330 * (1 - pow(((float) pressure/p0), 0.190295)); // Low pass filter LowPassAltitude=LowPassAltitude+(altitude - LowPassAltitude)*0.1; #ifdef DEBUG_BMP085 Serial.print("Temperature: "); Serial.print(temperature, DEC); Serial.println(" *0.1 deg C"); Serial.print("Pressure: "); Serial.print(pressure, DEC); Serial.println(" Pa"); Serial.print("Altitude: "); Serial.print(altitude, 2); Serial.println(" m"); Serial.println(); Serial.print("Low_Pass_Altitude: "); Serial.print(LowPassAltitude, 2); Serial.println(" m"); Serial.println(); Serial.print("PWM "); Serial.print(PWMval, 2); Serial.println(); #endif //delay(tempomesure); /////////////////////////////////////////////////////////////// // make a string for assembling the data to log: String dataString = ""; //OLD //t0 = t0 + (millis() - prevMillis); //NEW t0 = millis(); /* #ifdef DEBUG Serial.print("millis():"); Serial.print(millis()); Serial.print(","); Serial.print("t0:"); Serial.print(t0); Serial.print(","); #endif */ unsigned int alti = altitude*100; unsigned long pressu = pressure; unsigned int tempe = temperature; unsigned int LPalti = LowPassAltitude*100; unsigned int PWM = PWMval; dataString = String(t0) + "," + String(alti) + "," + String(LPalti) + "," + String(pressu) + "," + String(tempe)+ "," + String(PWM); // open the file. note that only one file can be open at a time, // so you have to close this one before opening another. //File dataFile = SD.open("DATA.txt", FILE_WRITE); File dataFile = SD.open(name, FILE_WRITE); // if the file is available, write to it: if (dataFile) { dataFile.println(dataString); dataFile.close(); #ifdef DEBUG // print to the serial port too: Serial.println(dataString); #endif } // if the file isn't open, pop up an error: else { Serial.println("error opening datalog.txt"); }//fin du if dataFile prevMillis = millis(); } }// fin de loop //--------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------- // Stores all of the bmp085's calibration values into global variables // Calibration values are required to calculate temp and pressure // This function should be called at the beginning of the program void bmp085Calibration() { ac1 = bmp085ReadInt(0xAA); ac2 = bmp085ReadInt(0xAC); ac3 = bmp085ReadInt(0xAE); ac4 = bmp085ReadInt(0xB0); ac5 = bmp085ReadInt(0xB2); ac6 = bmp085ReadInt(0xB4); b1 = bmp085ReadInt(0xB6); b2 = bmp085ReadInt(0xB8); mb = bmp085ReadInt(0xBA); mc = bmp085ReadInt(0xBC); md = bmp085ReadInt(0xBE); } // Calculate temperature given ut. // Value returned will be in units of 0.1 deg C short bmp085GetTemperature(unsigned int ut) { long x1, x2; x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15; x2 = ((long)mc << 11)/(x1 + md); b5 = x1 + x2; return ((b5 + 8)>>4); } // Calculate pressure given up // calibration values must be known // b5 is also required so bmp085GetTemperature(...) must be called first. // Value returned will be pressure in units of Pa. long bmp085GetPressure(unsigned long up) { long x1, x2, x3, b3, b6, p; unsigned long b4, b7; b6 = b5 - 4000; // Calculate B3 x1 = (b2 * (b6 * b6)>>12)>>11; x2 = (ac2 * b6)>>11; x3 = x1 + x2; b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2; // Calculate B4 x1 = (ac3 * b6)>>13; x2 = (b1 * ((b6 * b6)>>12))>>16; x3 = ((x1 + x2) + 2)>>2; b4 = (ac4 * (unsigned long)(x3 + 32768))>>15; b7 = ((unsigned long)(up - b3) * (50000>>OSS)); if (b7 < 0x80000000) p = (b7<<1)/b4; else p = (b7/b4)<<1; x1 = (p>>8) * (p>>8); x1 = (x1 * 3038)>>16; x2 = (-7357 * p)>>16; p += (x1 + x2 + 3791)>>4; return p; } // Read 1 byte from the BMP085 at 'address' char bmp085Read(unsigned char address) { unsigned char data; Wire.beginTransmission(BMP085_ADDRESS); Wire.write(address); Wire.endTransmission(); Wire.requestFrom(BMP085_ADDRESS, 1); while(!Wire.available()) ; return Wire.read(); } // Read 2 bytes from the BMP085 // First byte will be from 'address' // Second byte will be from 'address'+1 int bmp085ReadInt(unsigned char address) { unsigned char msb, lsb; Wire.beginTransmission(BMP085_ADDRESS); Wire.write(address); Wire.endTransmission(); Wire.requestFrom(BMP085_ADDRESS, 2); while(Wire.available()<2) ; msb = Wire.read(); lsb = Wire.read(); return (int) msb<<8 | lsb; } // Read the uncompensated temperature value unsigned int bmp085ReadUT() { unsigned int ut; // Write 0x2E into Register 0xF4 // This requests a temperature reading Wire.beginTransmission(BMP085_ADDRESS); Wire.write(0xF4); Wire.write(0x2E); Wire.endTransmission(); // Wait at least 4.5ms delay(5); // Read two bytes from registers 0xF6 and 0xF7 ut = bmp085ReadInt(0xF6); return ut; } // Read the uncompensated pressure value unsigned long bmp085ReadUP() { unsigned char msb, lsb, xlsb; unsigned long up = 0; // Write 0x34+(OSS<<6) into register 0xF4 // Request a pressure reading w/ oversampling setting Wire.beginTransmission(BMP085_ADDRESS); Wire.write(0xF4); Wire.write(0x34 + (OSS<<6)); Wire.endTransmission(); // Wait for conversion, delay time dependent on OSS delay(2 + (3<<OSS)); // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB) Wire.beginTransmission(BMP085_ADDRESS); Wire.write(0xF6); Wire.endTransmission(); Wire.requestFrom(BMP085_ADDRESS, 3); // Wait for data to become available while(Wire.available() < 3) ; msb = Wire.read(); lsb = Wire.read(); xlsb = Wire.read(); up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS); return up; } Testujemy. Jak? Po zaprogramowaniu, nie odpinamy ukladu od komputera, tylko w srodowisku arduino otwieramy okno "monitor szeregowy", predkosc transmisji ustawiamy na 9600 i cieszymy sie z efektow naszej pracy. Najważniejsze, czyli JAK TO DZIALA? Uklad podlaczamy pod wolny kanal odbiornika (zasilanie 5V). Od razu po wlaczeniu, program sprawdza czy obecna jest karta SD, nastepnie tworzony jest na karcie plik TXT z kolejnym numerkiem w nazwie i urzadzonko zaczyna w nim zapisywac: czas (ms), cisnienie (hPa), wysokosc bezwzgledna(m n.p.m.), wysokosci bezwzgledna po filtrze dolnoprzepustowym(m n.p.m.), wartosc PWM zczytana z kanalu w ktory wpiety jest logger. Czas pomiedzy kolejnymi zapisami to okolo 2sek. Poziom PWM osobiscie wykorzystuje jako znacznik, kiedy zmieniam w terenie parametry lotu i pozniej w domu analizujac chce wiedziec dokladnie ktora czesc barografki odpowiada jakiemu ustawieniu modelu. Odczyt danych: Wyjmujemy karte mikroSD, wkladamy do czytnika i zgrywamy pliki *.txt. Nastepnie otwieramy plik txt przy pomocy excela, wybierajac jako separator przecinek ",". W kolejnych kolumnach mamy zapisane: >> czas [ms] >> cisnienie [hPa] >> wysokosc bezwzgledna [m n.p.m.] >> wartosc wysokosci po filtrze dolnoprzepustowym [m n.p.m.] >>Wartość PWM Mam nadzieje ze nie popelnilem tu zadnych bledow, dlatego jesli ktos sie pokusi o poskladanie loggera prosze o info czy wszystko jest OK. =================================================================================== Kolejny projekt to wariometr. Urzadzenie pracujace na 433MHz, no i niestety cena juz jest znaczaco wyzsza, bo wynosci bedzie okolo 21zl. Zakupy: nadajnik latajacy w modelu: 1) plytka arduino pro mini (1,25$) 2) plyteczka z czujnikiem cisnienia BMP180 (2,50$) 3) nadajnik i odbiornik na 433MHz ( odbiornik XY-MK-5V, nadajnik fs1000a) (0,60$) 4) kabelek od serwa (z szuflady - 0$). odbiornik na ziemi: 5) wzmacniacz audio (scalak LM386, w PL jakies 2zl) 6) jakis glosniczek - ja skorzystalem ze starej kolumienki od glosnikow komputerowych (skorzystalem z tej z gniazdem jack oraz potencjometrem z wylacznikiem). 7) bakteria (ja uzywam lipola 2s i stabilizatora 7805). No to zaczynamy. Cale wario opisane jest bardzo dokladnie tu: https://www.rcgroups.com/forums/showthread.php?t=1749208 oraz tu bardziej zaawansowana wersja: http://www.modelbouwforum.nl/threads/poor-mans-vario.199904/page-5 Nadajnik: Podlaczenie kabelka serwa do arduino robimy jak w schemacie z dataloggera z ta roznicza ze przewod sygnalu PWM podpinamy pod pin 3 arduino. Czujnik cisnienia podpinamy jak na schemacie dataloggera. Nadajnik fs1000a podpinamy w nastepujacy sposob: GND - do GND arduino czyli (-) zasilania DATA - do pinu 2 arduino. VCC - do VCC 5V arduino. AND - dolutowac tu nalezy antenke w postaci przewodu o dlugosci 16,5cm Odbiornik Zaczynamy od podpiecia do osbiornika zasilania 5V pomiedzy VCC i GND, oraz glosniczka pomiedzy DATA i GND. Do AND dolutowujemy kabelek 16,5cm. Program: //********************************** //* BMP085 and BMP180 version * //********************************** // This is the Poor Mans Vario code for the cheaper BMP085 and the BMP180 sensor by BOSCH Sensortec // Arduino <> Sensor: Connect VCC to VCC and GND to GND, SCL goes to analogue pin 5, SDA to analogue pin4. // Servo signal input, connect to Arduino pin D3 // Audio output to transmitter on pin D2 // All code by Rolf R Bakke, Oct 2012 // Modified by Hans Meijdam, June 2013: added altitude feature // Modified by Hans Meijdam, November 2013: Sensor routine created for BMP085 and BMP180. // Modified by Hans Meijdam, July 2014: BETA Version // - Switch to select if whole meters are called out if below 100 meters altitude // - Deadband to make vario silent if no certain climb or sink level is achieved // - Negative altitude becomes now indicated as if it was positive altitude // // // ****** This is a customizable variable that acts as a switch ***** // choose "1" if you also want to hear the altitude in meters if you fly below 100 meters. // choose "0" if you only want to hear the 10 meters rounded altitude at all times. // Default is 0. // const byte altitude_per_meter = 0; // only altitude in 10 meters const byte altitude_per_meter = 1; // altitude in whole meters if below 100 meters // ****** This is a customizable variable (0 - 500 range) that defines how large the dead band is ****** // A dead band of "0" (= default) means that the vario will beep constantly, even with no climb or sink at all. // A small dead band (e.g. value 25 - 50) means that with a small amount of climb or sink the vario will start beeping // A medium dead band (e.g. value 50 - 100) means that the vario will be silent, unless it observes a medium rate of climb or medium rate of sink. // A high dead band (> 100) makes the vario only active at high rates of sink or climb. // int deadband = 0; // no deadband or deadband defined by potmeter int deadband = 25; // small deadband // int deadband = 75; // medium deadband // int deadband = 150; // large deadband // ****** Alternatively the deadband can be dynamically set by connecting a 10K potmeter over pins 12, A1 (rocker) and A2 ****** const byte deadbandpotmeter = 0; // no deadband potmeter present // const char deadbandpotmeter = 1; // deadband potmeter is present (10K potmeter over pins 12, A1 (rocker) and A2) #include "Wire.h" 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; int analogpin1 = 0; void setup() { pinMode(A2, OUTPUT); // Prepare for high end of potmeter pinMode(12, OUTPUT); // Prepare for low end of potmeter pinMode(A1, INPUT_PULLUP); // Prepare for potmeter input digitalWrite(A2, HIGH); // High end potmeter to 5 volt digitalWrite(12, LOW); //Low end potmeter to 0 volt Serial.begin(9600); // start serial for output analogpin1 = analogRead(1); // read the input pin A1 potmeter value // Serial.print("Analog pin A0 value: "); // Serial.println(analogpin1); // 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() { bmp085_read_temperature_and_pressure(&temperature,&pressure); // Serial.print(temperature,DEC); // Serial.print(" "); // Serial.println(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.print(altitude); altitude = abs(altitude); // if flying from hills negative altitude becomes indicated as positive lowpassFast = lowpassFast + (flpressure - lowpassFast) * 0.2; lowpassSlow = lowpassSlow + (flpressure - lowpassSlow) * 0.1; toneFreq = (lowpassSlow - lowpassFast) * 50; toneFreqLowpass = toneFreqLowpass + (toneFreq - toneFreqLowpass) * 0.1; toneFreq = constrain(toneFreqLowpass, -500, 500); ddsAcc += toneFreq * 100 + 2000; Serial.print(" ddsAcc: "); Serial.println(ddsAcc); if (deadbandpotmeter == 1) { analogpin1 = analogRead(1); // read the input pin A1 potmeter value deadband = map(analogpin1, 0, 1024, 500, 0); // map potmeter value to deadband range from 500 - 0 } if (toneFreq < 0 || ddsAcc > 0) { if (abs(toneFreq)>deadband) { tone(2, toneFreq + 550); ledOn(); // the Arduino led will blink if the Vario plays a tone, so you can test without having audio connected } } else { noTone(2); 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(2); // create 750 ms of silence, or you won't hear the first altitude beep ledOff(); delay(750); if(hundreds == 0) { tone(2,900); //long duration tone if the number is zero ledOn(); delay(600); noTone(2); ledOff(); } else for(char a = 0; a < hundreds; a++) //this loop makes a beep for each hundred meters altitude { tone(2,900); // 900 Hz tone frequency for the hundreds ledOn(); delay(200); noTone(2); ledOff(); delay(200); } delay(750); //longer delay between hundreds and tens if(tens == 0) { tone(2,1100); //long pulse if the number is zero ledOn(); delay(600); noTone(2); ledOff(); } else for(char a = 0; a < tens; a++) //this loop makes a beep for each ten meters altitude { tone(2,1100); //1100 Hz tone frequency for the tens ledOn(); delay(200); noTone(2); ledOff(); delay(200); } if (altitude_per_meter == 1 && hundreds == 0) { delay(750); //longer delay between tens and ones if(ones == 0) { tone(2,1300); //long pulse if the number is zero ledOn(); delay(600); noTone(2); ledOff(); } else for(char a = 0; a < ones; a++) //this loop makes a beep for each meter altitude { tone(2,1300); //1300 Hz tone frequency for the ones ledOn(); delay(200); noTone(2); ledOff(); delay(200); } } } } 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); } Jak to dziala? Nadajniczek wariometru wpinamy w wolny slot w odbiorniku RC (zasilanie 5V) sterowany w aparaturze rc przelacznikiem. Dzialanie zalezy od ustawienia wspomnianego przelacznika: W pierwszej skrajnej pozycji wariometr mierzy wysokosc, przepuszcza przez dwa filtry dolnoprzepustowe a z roznicy wartosci miedzy wynikami z tych dwoch filtrow wylicza czestotliwosc dzwieku. Wysyla sygnal do nadajnika, a odbiornik nie robi nic poza odbiorem analogowego sygnalu i wysterowaniem glosniczka. W drugiej skrajnej pozycji przelacznika wariometr "pikajac" podaje wysokosc. Wyjasnione jest to w komentarzach w kodzie programu. Cieszymy sie z dzialania, ale... jest cicho i zasieg na kilka metrow. Czyli slabo. Operacja pierwsza - modyfikacja odbiornika: Odbiornik musimy wyposarzyc we wzmacniacz audio. W tym celu wykorzystamy scalony wmacniacz LM386 oraz stara kolumne od glosnikow komputerowych, w ktorej znajdziemy glosnik, potencjometr i gniazdko sluchawkowe (pomocne gdy na startowisku jest wiecej niz jeden modelarz). Korzystamy z tego schematu: Czy to trudne? Nie wzmacniacz z powodzeniem mozemy poskladac "na pajaka", Vin to nasz sygnal z odbiorniczka (dwa zwarte piny podpisane DATA), sygnal ten trafia na dzielnik z potencjometru i na noge nr 3 ukladu scalonego. Noga 2 i 4 zwieramy do GND, noge nr 6 podpinamy do zasilania 5v. Noge nr 5 zapinamy do masy przez maly kondensator 0,05uF i opornik 10ohm. Glosnik wpinamy miedzy GND i noge nr 5 - szeregowo z kondensatorem elektrolitycznym 250uF Koszt super wzmiacniacza - 5zl Operacja druga - modyfikacja anteny odbiornika: Duzo lepszy zasieg otrzymamy stosujac zamiast antenki "bacika" antene typu dipol. Co potrzebujemy? Ok 50cm przewodu ekranowanego (np tego miedzy komputerem a wspomnianymi starymi glosniczkami). Jeden koniec podpinamy do odbiornika: >>ekran do GND >>zyla do ANT Na drugim koncu przewodu wykonujemy antene: Odizolowac nalezy 16,5cm przewodu i oddzielic ekranosobno i zyle sygnalowa osobno. Nastepnie odgiac ekran w jedna strone a zyle sygnalowa w druga, tak aby z przewodem do odbiornika utworzyly ksztalt litery T, lub Y. Oczywiscie konstrukcje dobrze jest usztywnic drewnianym patyczkiem lub precikiem z tworzywa sztucznego. Zdjecie zaporzyczone z sasiedniego forum Operacja trzecia - zasilanie nadajnika: Bardzo waznym parametrem wyplywajacym bezposrednio na moc nadawanego sygnalu jest napiecie zasilania nadajnika. Skoro tak, to przy samym nadajniku miedzy piny GND i VCC nalezy wlutowac kondensator elektrolityczny (wystarczy 100uF, nalezy pamietac o polaryzacji kondensatora elektrolitycznego). Osobiscie zasilam model z lipo 2S 7,2V przez tzw BEC. Zasilajac wariometr z odbiornika RC zasilam go napieciem 5V. Zatem prosta modyfikacja znacznie poprawiajaca zasieg, jest odlutowanie przewodu zasilajacego pomiedzy arduino i nadajniczkiem VCC fs1000a. I zasilenie nadajniczka 433MHz bezposrednio z lipola (np. z gniazda balansera - jak na foto mojego wariometru: Schematy nadajnika po wspomnianych modyfikacjach zasilania: jakie Schemat odbiornika ze wzmacniaczem i antena dipol Mam nadzieje ze nic nie pomylilem, poniewaz schematy powstaly tylko na potrzebe tego postu. Na zdjeciu mojego wario widać, że fioletowy przewod podlaczany do lipola wchodzi pod termokurcza na arduino i dopiero tam jest polaczony z zasilajacym przewodem do nadajniczka. A to dlatego, ze pod termokurczem zrobiony jest dzielnik napiecia z dwoch rezystorow i podlaczony do wejscia analogowego arduino. Chodzi o to ze arduino ma mierzyc napiecie na lipolu i w momencie spadku ponizej zadanej wartosci w glosniku wariometru ma byc slyszalny alarm. Przedstawie to rozwiazanie ponizej. ====================================================================================== Wariometr modelarski z pomiarem napiecia baterii lipo i alarmem rozladowanej baterii Wariometr wykonujemy dokladnie tak jak to opisano powyzej, w wersji podlaczenia zasilania nadajnika fs1000a bezposrednio do lipola 2S (napiecie pomiedzy 8,4V a 7,2V). Jedyna modyfikacją jest dolutowanie dzielnika napiecia zrobionego z dwoch opornikow 10kOhm. Zgodnie ze schematem: Oczywiscie pamietajmy, ze wszystkie piny w arduino podpisane GND sa ze soba zwarte, podobnie piny VCC. Chcac podlutowac sie pod mase od nas zalezy ktory pin podpisany GND wybierzemy. Dlatego ponizsze zdjecia przedstawiajace moje wario nie sa w 100% zgodne ze schematem: Wariometr bez koszulki: Zblizenie na podlaczenie na plytce arduino: Komplet elektroniki jaki lata w moim modelu (oczywiscie plus serwa): Kod programu: //********************************** //* BMP085 and BMP180 version * //********************************** // This is the Poor Mans Vario code for the cheaper BMP085 and the BMP180 sensor by BOSCH Sensortec // Arduino <> Sensor: Connect VCC to VCC and GND to GND, SCL goes to analogue pin 5, SDA to analogue pin4. // Servo signal input, connect to Arduino pin D3 // Audio output to transmitter on pin D2 // All code by Rolf R Bakke, Oct 2012 // Modified by Hans Meijdam, June 2013: added altitude feature // Modified by Hans Meijdam, November 2013: Sensor routine created for BMP085 and BMP180. // Modified by Hans Meijdam, July 2014: BETA Version // - Switch to select if whole meters are called out if below 100 meters altitude // - Deadband to make vario silent if no certain climb or sink level is achieved // - Negative altitude becomes now indicated as if it was positive altitude // // // ****** This is a customizable variable that acts as a switch ***** // choose "1" if you also want to hear the altitude in meters if you fly below 100 meters. // choose "0" if you only want to hear the 10 meters rounded altitude at all times. // Default is 0. // const byte altitude_per_meter = 0; // only altitude in 10 meters const byte altitude_per_meter = 1; // altitude in whole meters if below 100 meters // ****** This is a customizable variable (0 - 500 range) that defines how large the dead band is ****** // A dead band of "0" (= default) means that the vario will beep constantly, even with no climb or sink at all. // A small dead band (e.g. value 25 - 50) means that with a small amount of climb or sink the vario will start beeping // A medium dead band (e.g. value 50 - 100) means that the vario will be silent, unless it observes a medium rate of climb or medium rate of sink. // A high dead band (> 100) makes the vario only active at high rates of sink or climb. // int deadband = 0; // no deadband or deadband defined by potmeter int deadband = 25; // small deadband // int deadband = 75; // medium deadband // int deadband = 150; // large deadband // ****** Alternatively the deadband can be dynamically set by connecting a 10K potmeter over pins 12, A1 (rocker) and A2 ****** const byte deadbandpotmeter = 0; // no deadband potmeter present //const char deadbandpotmeter = 1; // deadband potmeter is present (10K potmeter over pins 12, A1 (rocker) and A2) #include "Wire.h" 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; int analogpin1 = 0; int analogpin2 = 0; int voltage; void setup() { pinMode(A0, INPUT); // pomiar npiecia baterii pinMode(A2, OUTPUT); // Prepare for high end of potmeter pinMode(12, OUTPUT); // Prepare for low end of potmeter pinMode(A1, INPUT_PULLUP); // Prepare for potmeter input digitalWrite(A2, HIGH); // High end potmeter to 5 volt digitalWrite(12, LOW); //Low end potmeter to 0 volt Serial.begin(9600); // start serial for output analogpin1 = analogRead(A1); // read the input pin A1 potmeter value Serial.print("Analog pin A1 value: "); Serial.println(analogpin1); // 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() { // Pomiar napiecia baterii, wartosc napiecia mnozona *10. analogpin2 = analogRead(A0); // read the input pin A0 potmeter value voltage = map(analogpin2, 0, 1024, 0, 100); // map potmeter value to deadband range from 0 - 100 (0-10v) Serial.print("voltage= "); Serial.print(voltage,DEC); Serial.println("V"); if (voltage < 74) // jezeli napiecie pakietu nizsze niz 7,4v >> wlacz alarm { tone(2, 3000); delay(100); noTone(2); delay(100); tone(2, 3000); delay(100); noTone(2); delay(100); } bmp085_read_temperature_and_pressure(&temperature,&pressure); // Serial.print(temperature,DEC); // Serial.print(" "); // Serial.println(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.print(altitude); altitude = abs(altitude); // if flying from hills negative altitude becomes indicated as positive lowpassFast = lowpassFast + (flpressure - lowpassFast) * 0.2; lowpassSlow = lowpassSlow + (flpressure - lowpassSlow) * 0.1; toneFreq = (lowpassSlow - lowpassFast) * 50; toneFreqLowpass = toneFreqLowpass + (toneFreq - toneFreqLowpass) * 0.1; toneFreq = constrain(toneFreqLowpass, -500, 500); ddsAcc += toneFreq * 100 + 2000; Serial.print(" ddsAcc: "); Serial.println(ddsAcc); if (deadbandpotmeter == 1) { analogpin1 = analogRead(A1); // read the input pin A1 potmeter value deadband = map(analogpin1, 0, 1024, 500, 0); // map potmeter value to deadband range from 500 - 0 } if (toneFreq < 0 || ddsAcc > 0) { if (abs(toneFreq)>deadband) { tone(2, toneFreq + 550); ledOn(); // the Arduino led will blink if the Vario plays a tone, so you can test without having audio connected } } else { noTone(2); 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(2); // create 750 ms of silence, or you won't hear the first altitude beep ledOff(); delay(750); if(hundreds == 0) { tone(2,900); //long duration tone if the number is zero ledOn(); delay(600); noTone(2); ledOff(); } else for(char a = 0; a < hundreds; a++) //this loop makes a beep for each hundred meters altitude { tone(2,900); // 900 Hz tone frequency for the hundreds ledOn(); delay(200); noTone(2); ledOff(); delay(200); } delay(750); //longer delay between hundreds and tens if(tens == 0) { tone(2,1100); //long pulse if the number is zero ledOn(); delay(600); noTone(2); ledOff(); } else for(char a = 0; a < tens; a++) //this loop makes a beep for each ten meters altitude { tone(2,1100); //1100 Hz tone frequency for the tens ledOn(); delay(200); noTone(2); ledOff(); delay(200); } if (altitude_per_meter == 1 && hundreds == 0) { delay(750); //longer delay between tens and ones if(ones == 0) { tone(2,1300); //long pulse if the number is zero ledOn(); delay(600); noTone(2); ledOff(); } else for(char a = 0; a < ones; a++) //this loop makes a beep for each meter altitude { tone(2,1300); //1300 Hz tone frequency for the ones ledOn(); delay(200); noTone(2); ledOff(); delay(200); } } } } 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); } Jak to dziala? W glownej ptli programu mierzone jest napiecie na pinie A0 do ktorego podlaczone przez dzielnik jest zasilanie z lipolka. Sygnal przeliczany jest na wartosc napiecia brutto na lipolu mnozona *10. Jesli warunek jest spelniony napiecie<7,4V (w programie warunek "voltage<74 ")w glosniku uslyszymy charaktrystyczne pikanie. Oczywiscie wartosc 7,4v mozemy zmieniac dowolnie. Nalezy jednak pamietac ze pomiar napiecia jest wzgledem napiecia zasilania procesora w arduino 5V. Czyli jesli napiecie lipolka spadnie na tyle, ze po BECu napiecie bedzie nizsze niz wspomniane 5V, pomiar bedzie obarczony bledem. Obawiam sie, czy spadki napiecia spowodowane przez dzialajace serwa, nie beda powodowaly zadzialanie alarmu. Jesli tak, dopisze filtr dolnoprzepustowy na pomiar napiecia. Niestety teraz pogoda nie nastraja na proby terenowe, a tylko wtedy bede wiedzial czy pomiar dziala jak nalezy. 3
d2f Opublikowano 18 Listopada 2016 Opublikowano 18 Listopada 2016 Zrobiłeś prawie to samo co ja :-) Zaraz będzie wysyp open alti loggerów ;-#
kr3cik Opublikowano 19 Listopada 2016 Opublikowano 19 Listopada 2016 Szczerze, pogniotłeś mi moją młodą psychikę Wygląda to zbyt pięknie żeby mogło być prawdziwe. Mam nadziej, że uda mi się zrobić taki wariometr
d2f Opublikowano 20 Listopada 2016 Opublikowano 20 Listopada 2016 Ja od razu korzystam z funkcji dla tego czujnika zwracającej wysokość na podstawie pierwszego pomiaru ciśnienia.Wychodzi mniejszy plik i szybciej się zapisuje na wolnych kartach (ot 3 bajty zamiast 6) i chyba na to znaczenie przy bieżących niskich temperaturach. ---Edit Coś mi się nie wszystko z pierwszego posta wyświetliło w taplatalku, wobec czego po ponownym obejrzeniu wątku na PC - to co wyżej napisałem - jest jakoś tak średnio odkrywcze ;-)
Gość Opublikowano 25 Listopada 2016 Opublikowano 25 Listopada 2016 ... tani logger wysokości ... Testujemy. Jak? Po zaprogramowaniu, nie odpinamy ukladu od komputera, tylko w srodowisku arduino otwieramy okno "monitor szeregowy", predkosc transmisji ustawiamy na 9600 i cieszymy sie z efektow naszej pracy. ... Dało się uruchomić, wyniki są (ustrojstwo trzymane w ręku) Teraz tylko kawałek dobrej pogody by się przydał...
hornet20 Opublikowano 26 Listopada 2016 Autor Opublikowano 26 Listopada 2016 Zapis na SD działa poprawnie? Generalnie wykorzystasz tylko wartość czasu, wysokość po filtrze dolnoprzepustowym i ewentualnie PWM. Zapisywana jest też temperatura czujnika, niestety jest ona zazwyczaj o kilka stopni wyższa niż temperatura otoczenia.
Gość Opublikowano 26 Listopada 2016 Opublikowano 26 Listopada 2016 Zapis na kartę jest bez problemowy. Pliczek w załączniku. Zapis co ok. 30 sekund
d2f Opublikowano 26 Listopada 2016 Opublikowano 26 Listopada 2016 Chyba dlatego jest wyższa, bo płytka się grzeje. Zauważyłem że ten czujnik wystawiony na zewnątrz modelu ma mniejszy błąd względem otoczenia niż schowany w modelu. Ale nie ma co narzekać. Jest ultra tani. Zawsze można dołożyć ds18b20 jeśli zależy nam na dokładnym pomiarze temperatury. Prawie nic nie waży i jest mały.
hornet20 Opublikowano 26 Listopada 2016 Autor Opublikowano 26 Listopada 2016 Skoro zapis na kartę działa, to znaczy, ze schemat połączeń i wsad sa OK ciesze sie. Co do temperatury, to mierzona jest właśnie temperatura samego czujnika, bo jest ona potrzebna do kalibracji wskazań. Wystawianie poza model to chyba nie najlpszy pomysł ze względu na ciśnienie dynamiczne podczas lotu i błędne wskazania ciśnienia. Jednak dołożenie ds18b20 jest doskonałym pomysłem. Pytanie tylko po co mierzyć temperaturę ...może w przypadku motoszybowca gdzieś blisko silnika, albo baterii.
dariuszj Opublikowano 26 Listopada 2016 Opublikowano 26 Listopada 2016 Cieszymy sie z dzialania, ale... jest cicho i zasieg na kilka metrow. Czyli slabo. Jaki jest zasięg po tych wszystkich modyfikacjach? Da się uzyskać bezproblemowo kilkaset metrów? I druga kwestia - bardzo trudno by było zrobić wersję, która by podawała wysokość poprzez komunikaty głosowe?
zuczek Opublikowano 26 Listopada 2016 Opublikowano 26 Listopada 2016 Kiedyś również zrobiłem sobie taki prosty wariometr na bmp180 i błąd pomiaru wysokości u mnie wynosił około +-2 metry. U Was też są tak duże rozbieżności?
Gość Opublikowano 26 Listopada 2016 Opublikowano 26 Listopada 2016 Odczyt danych: Wyjmujemy karte mikroSD, wkladamy do czytnika i zgrywamy pliki *.txt. Nastepnie otwieramy plik txt przy pomocy excela, wybierajac jako separator przecinek ",". Drobna modyfikacja: w linii 77 String s = "dat" + String(++fileNum) + ".txt"; zmieniamy txt na csv: String s = "dat" + String(++fileNum) + ".csv"; w linii 127 save("t(ms),Altitude(m)*100,LowPassAltitude(m)*100,Pression(Pa),Temperature©*10,PWM"); zmieniamy przecinek na średnik: save("t(ms);Altitude(m)*100;LowPassAltitude(m)*100;Pression(Pa);Temperature©*10;PWM"); w linii 203 dataString = String(t0) + "," + String(alti) + "," + String(LPalti) + "," + String(pressu) + "," + String(tempe)+ "," + String(PWM); też zmieniamy przecinek na średnik: dataString = String(t0) + ";" + String(alti) + ";" + String(LPalti) + ";" + String(pressu) + ";" + String(tempe)+ ";" + String(PWM); Excel otwiera plik jak "swój"
d2f Opublikowano 26 Listopada 2016 Opublikowano 26 Listopada 2016 Kiedyś również zrobiłem sobie taki prosty wariometr na bmp180 i błąd pomiaru wysokości u mnie wynosił około +-2 metry. U Was też są tak duże rozbieżności?Gąbka na czujniku zmniejsza rozbieżności. Natomiast co do zasięgu - robiłem testy na takich modułach i uzyskałem max 62m latając idealnie nad odbiornikiem i ustawiając anteny równolegle w poziomie. Program był inny - m in nadawanie było co 2sekundy i z użyciem jakiegoś kodowania (już nie pamiętam). Ciągłość transmisji po ziemi miałem do max 30 m (odbierałem każdą paczkę). Powyżej tej odległości skuteczność odbioru spadała strasznie. Są inne moduły (np od open lrs) które mają większy zasięg i mniej wpływają na odbiornik rc.
hornet20 Opublikowano 26 Listopada 2016 Autor Opublikowano 26 Listopada 2016 Kiedyś również zrobiłem sobie taki prosty wariometr na bmp180 i błąd pomiaru wysokości u mnie wynosił około +-2 metry. U Was też są tak duże rozbieżności? Dlatego wyniki trzeba filtrować. Jaki jest zasięg po tych wszystkich modyfikacjach? Da się uzyskać bezproblemowo kilkaset metrów? I druga kwestia - bardzo trudno by było zrobić wersję, która by podawała wysokość poprzez komunikaty głosowe? Zasięg? Kluczowym jest, że transmisja jest analogowa (sygnalu audio), zatem trudno powiedzieć kiedy "zasięg jest" a kiedy juz sygnal jest na tyle slaby i trudny do wyłowienia z szumu i "zasiegu nie ma". Po zasileniu nadajnika prosto z lipo, oraz zbudowaniu anteny dipol na odbiornik ja nie tracę zasięgu (albo trace na chwilke przy zaslonieciu anteny przez weglowy kadlub) do 200m, niestety wtedy juz prawie nie widzę modelu. Moj max na wysokosci to 220m, ale juz tylko kropka na niebie i lot właśnie słuchając wariometru. Wplywu na link RC nie zaobserwowalem, pomimo iż obie anteny mam odsuniete jedynie o szerokosc kadluba. Komunikaty głosowe sa bardzo łatwe do zorganizowania, odtwarzacz mp3 na microSD kosztuje 2$, pytanie tylko po co? W tym rozwiązaniu transmisji sygnalu musiałby on latać w modelu. Jest to płytka 20x20mm i wazy kolejne kilka gramów. Tu jest minimum z minimum, czyli jak najtaniej i przede wszystkim - jak najmniejszy wymiar i jak najlżej . String s = "dat" + String(++fileNum) + ".txt"; zmieniamy txt na csv: String s = "dat" + String(++fileNum) + ".csv"; Ano calkiem fajne rozwiazanie, ja akurat mam zrobiony arkusz w Excelu, w którym makro samo otwiera plik, kopiuje dane i robi wykresy. Przy takim rozwiązaniu rozszerzenie nie ma znaczenia.
dariuszj Opublikowano 26 Listopada 2016 Opublikowano 26 Listopada 2016 Zasięg? Kluczowym jest, że transmisja jest analogowa (sygnalu audio), zatem trudno powiedzieć kiedy "zasięg jest" a kiedy juz sygnal jest na tyle slaby i trudny do wyłowienia z szumu i "zasiegu nie ma". Komunikaty głosowe sa bardzo łatwe do zorganizowania, odtwarzacz mp3 na microSD kosztuje 2$, pytanie tylko po co? W tym rozwiązaniu transmisji sygnalu musiałby on latać w modelu. Jest to płytka 20x20mm i wazy kolejne kilka gramów. Tu jest minimum z minimum, czyli jak najtaniej i przede wszystkim - jak najmniejszy wymiar i jak najlżej . W międzyczasie temat trochę rozeznałem i większego problemu z lepszymi modułami nadawczo - odbiorczymi za rozsądne pieniądze raczej nie ma. Rozumiem, że jest to wersja minimum i w DLG liczy się każdy gram. Mi zależy na wersji do innych modeli, gdzie te parę gram nie ma znaczenia natomiast ważniejsza jest funkcjonalność. Po co komunikaty głosowe? Przyzwyczaiłem się do vario Pitlaba, gdzie mogę w każdej chwili odpytać o wysokość. I mi się to przydaje w krążenie w "zerze". Vario co chwilę zmienia dźwięk i trudno określić czy model się minimalnie wznosi czy opada. Wtedy odpytuje o wysokość raz, za chwilę drugi raz i wiem czy mam noszenie czy model opada. Tutaj też ta funkcjonalność jest zaszyta, ale bez komunikatów głosowych praktycznie bezużyteczna. A generalnie to najchętniej widziałbym rozwiązanie, gdzie sygnał jest przekazywany na ziemię cyfrowo, potem przez bluetooth trafia do telefonu i tam jest obrabiany z dźwiękiem vario, komunikatami głosowymi, rejestracją danych, wykresami i odpowiednimi wskazaniami na wyświetlaczu smartfona. Niby są takie systemy telemetrii, ale to już jest niestety droższe i aplikacje do nich nie spełniają moich oczekiwań. Generalnie takie coś było by bardzo małe, lekkie i dość tanie. Tylko, żeby ktoś zechciał jeszcze napisać aplikację na smartfona. EDIT: Dziękuję za sugestię z tymi modułami MP3. Faktycznie sprawa wygląda prosto. Będę się musiał za to wziąć. Szkoda tylko, że ostatnio jednoukładówki coś programowałem blisko 20 lat temu i to w asemblerze.
hornet20 Opublikowano 26 Listopada 2016 Autor Opublikowano 26 Listopada 2016 Wybacz szczerość, ale tak lekko licząc za jednego Pitlaba zbudujesz 25 sztuk wariometrów z tego tematu, więc porównywanie funkcjonalności nie bardzo ma sens W międzyczasie temat trochę rozeznałem i większego problemu z lepszymi modułami nadawczo - odbiorczymi za rozsądne pieniądze raczej nie ma. To może podziel sie spostrzeżeniami. Bo akurat temat jest mi bliski i mam zupełnie inne zdanie na temat odbiorników w tym przedziale cenowym. A generalnie to najchętniej widziałbym rozwiązanie, gdzie sygnał jest przekazywany na ziemię cyfrowo, potem przez bluetooth trafia do telefonu i tam jest obrabiany z dźwiękiem vario, komunikatami głosowymi, rejestracją danych, wykresami i odpowiednimi wskazaniami na wyświetlaczu smartfona. Niby są takie systemy telemetrii, ale to już jest niestety droższe i aplikacje do nich nie spełniają moich oczekiwań. Generalnie takie coś było by bardzo małe, lekkie i dość tanie. Tylko, żeby ktoś zechciał jeszcze napisać aplikację na smartfona. To jest najlepsze rozwiazanie, zostaje kwestia zapychania odbiornika RC danymi z mocnego nadajnika latającego w modelu. No i.. jak latam, to nie patrze na telefon, zazwyczaj konczy sie to zgubieniem modelu na niebie Dużo łatwiejszym rozwiązaniem jest skorzystanie z dwukierunkowej komunikacji linku RC na 2,4GHz. Z czego np. protokoły FrSky oraz Hiteca są już opisane na sasiednim angielskojęzycznym forum. Wchodzi w gre albo wysylanie danych i wyswietlanie na aparaturze (np Aurorze Hiteca), albo wyprowadzenie sygnału z modułu nadawczego i jego interpretacja przez pikanie, sygnaly glosowe, przesylanie bluetootchem itp... Cena śmiesznie mala.. w sumie wychodzi taniej niż opisany tu wariometr
dariuszj Opublikowano 26 Listopada 2016 Opublikowano 26 Listopada 2016 Akurat vario Pitlaba nie posiada jakichś mega bajerów. I w opisanym tutaj właśnie wariometrze brakuje mi w zasadzie tylko komunikatów głosowych. Co do cen to mi nie zależy na wariometrze za 20 zł. 150-200 zł za lepszy czujnik ciśnienia i lepszy moduł nadawczy by było dla mnie jak najbardziej OK. A odbiór sygnału najchętniej bym widział na radiotelefonie LPD. Co do komunikacji linku RC na 2,4 GHz to oczywiście racja, ale ja chce to do 35 Mhz. I tutaj specjalny link 2,4 tylko do telemetrii się mija z celem, za drogo i trochę chyba jednak bez sensu.
hornet20 Opublikowano 26 Listopada 2016 Autor Opublikowano 26 Listopada 2016 EDIT: Dziękuję za sugestię z tymi modułami MP3. Faktycznie sprawa wygląda prosto. Będę się musiał za to wziąć. Szkoda tylko, że ostatnio jednoukładówki coś programowałem blisko 20 lat temu i to w asemblerze. Do mnie plytka mod-1021 dojechala w tym tygodniu i samo odtwarzanie dziala bardzo fajnie. Manual dostepny tu https://www.embeddedadventures.com/datasheets/MOD-1021_hw_v1.pdf Jednak przyznam ze jeszcze nie mam pomysłu jak w jeden drut wepchnąć sygnał audio modulowany przez procesor oraz sygnał z odtwarzacza mp3.
dariuszj Opublikowano 26 Listopada 2016 Opublikowano 26 Listopada 2016 Jednak przyznam ze jeszcze nie mam pomysłu jak w jeden drut wepchnąć sygnał audio modulowany przez procesor oraz sygnał z odtwarzacza mp3. Najprościej tak jak w pasywnych mikserach audio czyli poprzez rezystory na obu liniach plus ewentualnie dzielnik(i) napięcia dla ustalenia podobnego poziomu głośności. Przykład:
hornet20 Opublikowano 26 Listopada 2016 Autor Opublikowano 26 Listopada 2016 Z poziomem sygnalu problemu nie ma, bo sam odtwarzacz ma regulacje glosnosci. Przy czym da rade wyslac odrazu polecenie aby odtworzyc np sciezke numer 1 z glosnoscia 33% trzeba popróbować.
Rekomendowane odpowiedzi