DIY Vario 2.5$

Odpowiedz


To pytanie jest elementem zabezpieczającym przed automatycznym zamieszczaniem postów.
Emotikony
:D :) ;) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :!: :?: :idea: :arrow: :| :mrgreen: :geek: :ugeek:

BBCode włączony
[Img] włączony
[Flash] wyłączony
[URL] włączony
Emotikony włączone

Przegląd tematu
   

Rozwiń widok Przegląd tematu: DIY Vario 2.5$

Re: DIY Vario 2.5$

Post autor: R0bby » 08 lutego 2016, 15:49

Nie wiem czy masz jakieś pojęcie o programowaniu, to na wszelki wypadek napiszę:
linie zaczynające się od podwójnego slasha "//"są ignorowane przez kompilator. Tak samo jak bloki pomiędzy "/*" i "*/". Np. w ten sposób jest wykluczony ciąg instrukcji w funkcji "H2Snd()" bo razem z obsługą wyświetlacza nie mogłem pomieścić się w pamięci, poza tym, nie wiem czy tak duża gradacja sygnalizacji przy opadaniu jest niezbędna.

Bloki kompilacji warunkowej:

Kod: Zaznacz cały

// #define LCD_DEBUG

#ifdef LCD_DEBUG
  #include <LiquidCrystal_I2C.h>
#endif

znaczy tyle: jeśli LCD_DEBUG zostało zdefiniowane (w tym wypadku jest ignorowane przez //, więc nie jest zdefiniowane, to włącz do programu to co jest pomiędzy "ifdef" i "endif". Jeśli np. nie zamierzasz korzystać z monitoringu baterii to wpisz "//" przed tą sekwencją "#define BATTERY_MONITOR", a wszystkie bloki "BATTERY_MONITOR" zostaną przez kompilator pominięte.

I śmiało pisz, jakby co :)

Re: DIY Vario 2.5$

Post autor: wojtek » 08 lutego 2016, 07:48

Dzieki! Sproboje zrobic.

w.

Re: DIY Vario 2.5$

Post autor: R0bby » 07 lutego 2016, 08:34

Faktycznie, nie napisałem, chociaż w kodzie to widać

Kod: Zaznacz cały

#define SPEAKER 4
czyli plus głośnika na P4. Przy okazji jedna uwaga - Piny P3 i P4 modułu Attiny są wykorzystywane podczas wgrywania programu i jeśli coś, np. głośniczek, jest z nimi połączone, moduł nie zostanie rozpoznany przez programator i wgranie programu się nie uda. Krótko mówiąc, najpierw wgrywamy program, a potem montujemy.

Przy wykorzystaniu baterii od starej noki, jako obudowa idealnie pasuje pudełko po tic-tackach :)

Prowizorki są najlepsze, powiedział baca wiążąc buta dżdżownicą :) :)

Re: DIY Vario 2.5$

Post autor: wojtek » 07 lutego 2016, 03:37

Swietna sprawa, dzieki :)
Jedno pytanie (moze infantylne, ale dla kogos kto od biedy poradzi sobie lutownica, ale z teorii jest kompletna noga, chyba dosc wazne). Gdzie jest przylutowany glosnik? Ze zdjec wyglada, ze jeden przewod do masy, a drugi? Z gory dziekuje za odpowiedz.

w.

Re: DIY Vario 2.5$

Post autor: Michał T » 04 lutego 2016, 07:14

Pogratulować .

Re: DIY Vario 2.5$

Post autor: kris » 04 lutego 2016, 00:42

"Adam Słodowy"

Brawo
:)

Re: DIY Vario 2.5$

Post autor: Sław(ny) » 02 lutego 2016, 19:01

R0bby pisze:
Zdjęcia części i gotowego urządzenia - jak widać lutowanie nie jest moją najmocniejszą stroną ;)
http://r0bby.cba.pl/vario.htm



Lutowanie - 2
Projekt - 5

Sorry nie mogłem się powstrzymać :twisted:

Re: DIY Vario 2.5$

Post autor: R0bby » 02 lutego 2016, 18:20

Edytować postów to już nie można?
Zapomniałem napisać, ze taktowanie procesora należy wybrać w Arduino 1MHz.
Warto też usunąć z modułu Attiny diodę LED POWER - nie potrzebnie zabiera cenne mA :)

DIY Vario 2.5$

Post autor: R0bby » 02 lutego 2016, 17:43

Cześć,

Pisałem niedawno, że pracuję nad tanią pikawką. Vario pracuje na mikrokontrolerze Attiny85 i czujniku ciśnienia BMP180. Oprócz tych modułow do pracy wymagany jest jakiś brzęczyk (może być głośniczek ze starego telefonu. Ja zastosowałem przetwornik piezoelektryczny) i jakieś zasilanie. Attiny pracuję w zakresie 2.7-5.5V (użyłem baterii ze starej komórki). Układ w czasie pracy pobiera ok. 8mA, a w czasie wydawania dźwięku ok. 20mA. Aby uniknąć projektowania płytek, trawienia itp. użyłem gotowych modułow.

W modułach należy połączyć:
Attiny85 ----- BMP180
P0 ----------- SDA
P2 ----------- SCL
5V ----------- Vcc
GND ---------- GND

Dodatkowo (nie jest to konieczne do działania varia) zastosowałem kontrolę poziomu baterii, co wymaga użycia 2 rezystorów ( u mnie 220kom i 1 Mom, ale mogą być o innych wartościach, tylko trzeba stosownie zmodyfikować kod. Przy spadku napięcia baterii poniżej 3.2V dioda LED na płytce mikrokontrolera miga co 2 sekundy.

Podczas testów podłączałem dodatkowo wyświetlacz LCD 2x16 znaków z interfejsem I2C. Jak ktoś się chce pobawić to może sobie dokupić - obsługa wyświetlacza jest w kodzie.

Kod programu napisałem w Arduino. Moduł mikrokontrolera wyposażony jest w port USB i do programowania nic więcej nie jest wymagane. Moduł występuję w 2 wersjach portu USB - normalny wtyk, tzn USB A i mini USB A. Nie ma znaczenia który użyjesz.

Koszty:
moduł Attiny85 - 1.15$
moduł BMP180 - 1.20$

Wszystko z darmową wysyłką. Oczywiście można kupić na Allegro - będzie szybciej i kilka razy drożej.

Brzęczyka i akumulatorka nie liczę, bo takie śmieci każdy w domu ma.

Po kolei co trzeba zainstalować:
1. Ściągamy i instalujemy Arduino ( pracowałem na 1.6.5).
2. Doinstalowujemy płytę Attiny85 wg. instrukcji na stronie: http://digistump.com/wiki/digispark/tutorials/connecting
3. Doinstalowujemy biblioteki WireM i tinyBMP085.
4. Kompilujemy i wgrywamy.

Działanie:
Po włączeniu przez 5 sek nic się nie dzieje - Attiny czeka na ewentualne wgrywanie programu. Potem przy poprawnej komunikacji z BMP180 następuje 5 mrugnięć LED i vario zaczyna pracować. W razie niewykrycia czujnika ciśnienia dioda LED świeci się światłem ciągłym i vario nie pracuje.


UWAGA:
Jeśli ma być wykorzystywany monitoring baterii niezbędne jest zablokowanie funkcji RESET na pinie P5. Można tego dokonać tylko przy pomocy programatora, nie można tego cofnąć i traci się możliwość programowania przez programator. Tzn. można, ale trzeba mieć programator HV.

Tutaj próbka jak vario gra:
https://www.youtube.com/watch?v=PVbd9z2-FF8&feature=youtu.be
na wyświetlaczu ukazuje się indeks, częstotliwość dzwięku, długość trwania w ms, czas przerwy w ms. Te same dźwięki są zaprogramowane w vario. Warto "pod siebie" ustawić sobie progi załączania poszczególnych dźwięków. Jest to na tyle czytelne w kodzie, że nie powinno nikomu sprawiać problemu. Progi załączenia podane są w decymetrach. Np. kod

Kod: Zaznacz cały

if(dh > 3 )   { PLAY_CLIMB(0); return; }
załączy dźwięk o indeksie 0 przy wznoszeniu większym niż 3dm/sek.

Zdjęcia części i gotowego urządzenia - jak widać lutowanie nie jest moją najmocniejszą stroną ;)
http://r0bby.cba.pl/vario.htm

I kod:

Kod: Zaznacz cały

#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include <avr\power.h>
#include <util/delay.h>
#include <TinyWireM.h>
#include <tinyBMP085.h>

//   //CTC, toggle OC1B, clk/16, CLK/PSC=62.5kHz, 255=122.5Hz, 31=1008Hz
#define PLAYER_START  TCNT1=0; TCCR1 = _BV(CTC1) | _BV(CS12) | _BV(CS10)
#define PLAYER_STOP  TCCR1=0

// #define LCD_DEBUG

#ifdef LCD_DEBUG
  #include <LiquidCrystal_I2C.h>
#endif

#define BATTERY_MONITOR
#define BATTERY_LOW   56   // Uadc=U*Radc/(Radc+R), Aref=2.56V, R=1Mom, Radc=220kom, 3.2V=low => ADC=57 (real Up5=0.692V, ADC=69, Vcc=3.952V, dzielnik=0.175

#define SPEAKER 4
#define LED 1


#define PLAY_CLIMB(X)  beep_pause(pgm_read_word_near(vario_sound_climb + 3*(X)), pgm_read_word_near(vario_sound_climb + 3*(X)+1), pgm_read_word_near(vario_sound_climb + 3*(X)+2))
#define PLAY_SINK(X)  beep_pause(pgm_read_word_near(vario_sound_sink + 3*(X)), pgm_read_word_near(vario_sound_sink + 3*(X)+1), pgm_read_word_near(vario_sound_sink + 3*(X)+2))

const PROGMEM uint16_t vario_sound_climb[]={   //frequency (Hz), duration (ms), pause (ms),
                                    564, 540, 320,    // idx 0
                                    701, 438, 242,    // idx 1
                                    788, 368, 189,    // idx 2
                                    846, 312, 155,
                                    894, 259, 134,
                                    927, 219, 115,
                                    955, 176, 95,     // ....
                                    985, 138, 75,
                                    1008, 110, 55,
                                    1037, 81, 37,
                                    1070, 60, 30,
                                    1106, 46, 28,
                                    1141, 36, 28     // idx 12
                                    };

const PROGMEM uint16_t vario_sound_sink[]={
//                                    415, 600, 500,
                                    344, 600, 500,
                                    283, 600, 500,
/*                                    234, 600, 500,
                                    198, 600, 500,
                                    175, 600, 500,
                                    159, 600, 500,
                                    146, 600, 500,
                                    136, 600, 500,
                                    127, 600, 500     */
                                    };


volatile uint16_t sound_duration, pause_duration;
volatile uint8_t sek_1;

#ifdef LCD_DEBUG
  LiquidCrystal_I2C lcd(0x27, 16, 2);  // adres 0x27, 2x16 znakow
#endif

tinyBMP085 bmp;

void setup()
{

  pinMode(SPEAKER, OUTPUT);
  pinMode(LED, OUTPUT);

#ifdef LCD_DEBUG
  lcd.init();
  lcd.backlight();
#endif

   
  if (!bmp.begin(BMP085_STANDARD)){
    PORTB |= _BV(PB1);    // LED ON
    while(1);
  }
  else
    for(uint8_t i=0; i<10; i++)
      {
        PORTB ^= _BV(PB1);    // LED toggle
        _delay_ms(500);
      }
    PORTB &= ~_BV(PB1);    // LED OFF
   
//timer 1 - PLAYER
    GTCCR  = _BV(COM1B0);   // toggle P4
//timer 1 - koniec

//timer 0
    TCCR0A = _BV(WGM01);   // CTC
    TCCR0B = _BV(CS00) | _BV(CS01);   //prescaler 64,   
    OCR0A = 156; //  100Hz
    TIMSK = _BV(OCIE0A);
//timer 0 - koniec

#ifdef BATTERY_MONITOR
// ADC
    ADMUX =   _BV(ADLAR) | _BV(REFS1)| _BV(REFS2);   // vREF=2.56V, P5 analog input
    ADCSRA =  _BV(ADEN) |  _BV(ADPS2);    //ADC enable, PSC=16
// ADC - koniec
#endif

sei();
}

void loop()
{       
    static signed long alt=0, last_avr_alt=0, avr_alt=0;
    static uint8_t loop_counter=0;

#ifdef LCD_DEBUG   
     static byte flipflop=0;
#endif
   
    while(sek_1==0)
      {
        alt += bmp.readAltitudeSTDdm2();
        loop_counter++;   
      }
     
      sek_1 = 0;
      last_avr_alt = avr_alt;     
      avr_alt = alt / loop_counter;

#ifdef BATTERY_MONITOR
      ADCSRA |= _BV(ADSC);         // start conversion
      while (ADCSRA & _BV(ADSC) )
        {}
     
      if( ADCH < BATTERY_LOW)
          PORTB ^= _BV(PB1);
      else
          PORTB &= ~_BV(PB1);    // LED OFF
#endif

#ifdef LCD_DEBUG
      lcd.clear();         
      lcd.setCursor(0, 0);     
      if(flipflop==0){
        flipflop=1;
        lcd.print("H=");
//        lcd.print("U=");
//        lcd.print(ADCH, DEC);
        lcd.print(avr_alt/10);
      }else{
          flipflop=0;
          lcd.print("P=");         
          lcd.print(bmp.readPressure()/100); 
        }
      lcd.setCursor(9, 0);
      lcd.print("C=");     
      lcd.print(loop_counter, DEC);
#endif     
      alt = 0;
      loop_counter = 0;
      H2Snd( avr_alt - last_avr_alt ); 
}
                 
void H2Snd(int dh)  // tabelka zamiany roznicy wysokości na index
{
#ifdef LCD_DEBUG
      lcd.setCursor(0, 1);
      lcd.print("DH=");   //spacje zeby zmazac poprzednia wartosc     
      lcd.print(dh);
#endif

/*  if(dh < -90 )  { PLAY_SINK(7); return; }
  if(dh < -80 )  { PLAY_SINK(6); return; }
  if(dh < -70 )  { PLAY_SINK(5); return; }
  if(dh < -60 )  { PLAY_SINK(4); return; }
  if(dh < -50 )  { PLAY_SINK(3); return; }
  if(dh < -40 )  { PLAY_SINK(2); return; }    */ 
  if(dh < -35 )  { PLAY_SINK(1); return; }
  if(dh < -25 )  { PLAY_SINK(0); return; }
 
  if(dh > 120 ) { PLAY_CLIMB(12); return; }
  if(dh > 100 ) { PLAY_CLIMB(11); return; }
  if(dh > 88 )  { PLAY_CLIMB(10); return; }
  if(dh > 75 )  { PLAY_CLIMB(9); return; }
  if(dh > 63 )  { PLAY_CLIMB(8); return; }
  if(dh > 52 )  { PLAY_CLIMB(7); return; }
  if(dh > 42 )  { PLAY_CLIMB(6); return; }
  if(dh > 33 )  { PLAY_CLIMB(5); return; } 
  if(dh > 25 )  { PLAY_CLIMB(4); return; } 
  if(dh > 18 )  { PLAY_CLIMB(3); return; }
  if(dh > 12 )  { PLAY_CLIMB(2); return; }
  if(dh > 7 )   { PLAY_CLIMB(1); return; }
  if(dh > 3 )   { PLAY_CLIMB(0); return; }
 
  sound_duration=0;
  pause_duration=0;
#ifdef LCD_DEBUG
  lcd.setCursor(9, 1);
  lcd.print("f=     ");
#endif
}

void beep_pause(uint16_t frequency, uint16_t duration, uint16_t pause)
{

#ifdef LCD_DEBUG
  lcd.setCursor(9, 1);
  lcd.print("f="); 
  lcd.print(frequency);
#endif

  OCR1B = F_CPU/(frequency << 5); // PSC=16, F_CPU/(f*2*PRESCALER)
  OCR1C = F_CPU/(frequency << 5); // PSC=16, F_CPU/(f*2*PRESCALER)
  sound_duration = (duration+5)/10;//dlugość trwania w ms * f przerwania/1000 ms
  pause_duration = (pause+5)/10;
}

ISR(TIMER0_COMPA_vect)
{
static uint16_t _sound_duration=0, _pause=0, counter=0;

     if(_sound_duration>0)
      _sound_duration--;

     if(_sound_duration==0){           
          PLAYER_STOP;

          if(_pause>0)
              _pause--;

          if((_pause==0) && (sound_duration>0)){                       
              _sound_duration=sound_duration;                       
              _pause=pause_duration;             
              PLAYER_START;
          }
     }

     if(counter++ == 100){         
          counter=0;
          sek_1=1;               
      }
}

Na górę