Программирование BASCOM
GPS спидометр
Идея была сделать GPS спидометр для моторной лодки, чтобы можно было вмонтировать в панель, как обычный прибор. Вот результат:Функции:
- GPS Спидометр
- GPS координаты
- Одометр
- Текущий пробег, время в пути.
- Данные о предыдущей поездке.
- Суточный пробег
- Максимальная скорость
- Тахометр
- Моточасы
- Вольтметр
- Температура двигателя с индикацией перегрева
- Часы
В приборе используется:Большой ЖКИ фирмы МЭЛТ 20x4 с размером рабочего поля 123мм на 43мм.GPS приемник MC-1513.Датчик температуры DS18B20.Кнопка 1 служит для переключения режимов отображения (Главный экран->координаты->одометры->счетчик моточасов).Кнопка 2 сбрасывает все накопленные данные (нужно удерживать нажатой в момент подачи питания).Испытания пока проводились только на автомобиле (зима) и надо сказать, что он там прижился.«Камни».При пропадании питания все накопленные данные записываются в энергонезависимую память.Момент выключения определяется с помощью компаратора.При использовании, в качестве резервного питания, конденсатора 2200мкФ удавалось записать только 4 байта. С ионистором на 1F устройство работает после отключения питания около 18 секунд, но поскольку испытания проводились в машине при минусовой температуре, оказалось, что емкость ионистора падала в 10 раз. Хотя везде написано про их широкий температурный диапазон. В помещении свободно хватало ионистора в 0.1F.Модуль GPS MC-1513, при наличии на выходе RXA напряжения меньше 3.6 вольта, не подает признаков жизни, видимо так он определяет наличие подключения к принимающему устройству. (Два дня отнял...). Надо ещё сказать, что при минусовой температуре GPS перестает ловить спутники.На данный момент не решена только одна задача:При кратковременном отключении питания (а контроллер продолжает работать от ионистора) происходит вызов процедуры сохранения данных. Но после выхода из нее не редко происходит зависание контроллера. Положение спасает Watch Dog таймер без каких либо последствий для информации, но факт существования проблемы остается.При написании программы использовались части кода из статьи GPS логгер.Автор: Radan'Yashnov Dmitry N.Novgorod '********************************* '* Boat Comp V.1 Y.D.E. 2013 * '********************************* 'Маршрутный компьютер для моторной лодки 'GPS Спидометр,одометр, время в пути, суточный пробег, вольтметр, температура двигателя,часы, GPS координаты, максимальная скорость, 'тахометр, моточасы '***FUSES*** 'Boden level - 1 'Boden - 0 'Ext Crystal 101111 'OCD - 1 'JTAG - 1 'SPI - 0 'CKOPT - 1 'Erase EEPROM - 0 'Boot size - 00 'Reset vector -1 '***Концы*** '1wire - PORTA.1 'Umeter - PORTA.4 (ADC4) 'Taho - PORTB.1 (T1) 'Kn1 - PORTA.3 'Kn2 - PORTA.2 ' $regfile = "m16def.dat" $crystal = 11059000 $baud = 9600 $hwstack = 40 $swstack = 20 $framesize = 40 Config Lcdpin = Pin , Db4 = Portc.2 , Db5 = Portc.3 , Db6 = Portc.4 , Db7 = Portc.5 , E = Portc.1 , Rs = Portc.0 Config Lcd = 20 * 4 Config Serialin = Buffered , Size = 100 Config Adc = Single , Prescaler = Auto , Reference = Internal_2.56 Start Adc Config 1wire = Porta.1 Config Watchdog = 2048 Const Delitel = 1 'делитель количество импульсов на один оборот двигателя Const T_control = 95 'пороговое значение температуры для предупреждения Dim Flag As Bit Dim Data_izm As Bit Dim Tputi_h As Byte Dim Tputi_m As Byte Dim Tputi_s As Byte Dim Tputi_h_last As Byte Dim Tputi_m_last As Byte Dim Kn_on As Bit Dim Um As Byte Dim Uh As Byte Dim C As Byte , A As Byte Dim Dsp As Byte Dim Dsp1 As Byte Dim Spd0 As Byte Dim Ar(8) As Byte Dim Leng As Byte Dim Hh As Byte Dim Max_speed As Byte Dim U As Word Dim T As Integer , I As Integer Dim Speed As Integer Dim Road_last As Single Dim Spd2 As Single Dim Spd3 As Single Dim Road As Single Dim Road_all As Single Dim Road_day As Single Dim Tah As Single Dim Moto_h As Integer Dim Moto_m As Byte Dim Moto_s As Byte Dim Day As String * 2 Dim T_day As String * 2 Dim Temp As String * 6 Dim Uts As String * 10 Dim Hhs As String * 2 Dim Mm As String * 2 Dim Dot As String * 1 Dim Av As String * 2 Dim Lat As String * 12 Dim Ns As String * 2 Dim Lon As String * 13 Dim Ew As String * 2 Dim Spd As String * 6 Dim Crs As String * 6 Dim Da4 As String * 8 Dim Sat As String * 2 Dim Gpsfix As String * 1 Dim Ee_road_last As Eram Single Dim Ee_road_all As Eram Single Dim Ee_road_day As Eram Single Dim Ee_tputi_h As Eram Byte Dim Ee_tputi_m As Eram Byte Dim Ee_max_speed As Eram Byte Dim Ee_day As Eram String * 2 Dim Ee_moto_h As Eram Integer Dim Ee_moto_m As Eram Byte Dim Ee_moto_s As Eram Byte Deflcdchar 0 , 19 , 9 , 5 , 18 , 29 , 1 , 1 , 32 ' спецсимволы для ЖКИ Deflcdchar 1 , 32 , 32 , 10 , 31 , 17 , 31 , 31 , 32 ' Deflcdchar 5 , 24 , 26 , 2 , 7 , 2 , 2 , 3 , 32 ' Declare Sub Getline Declare Sub Wait_for_string(byval S As String) Declare Function Read_string() As String Config Timer0 = Timer , Prescale = 256 Config Timer1 = Counter , Edge = Falling 'подсчет импульсов тахометра On Timer0 Pulse: 'прерывания для опроса кнопок Config Pinb.1 = Input ' Config Pinb.3 = Input ' ногу AIN1 на вход Config Aci = On , Compare = Off , Trigger = Rising 'компаратор задействован для определения момента отключения питания On Aci Save_eeprom ' подпрограмма прерывания от компаратора для записи в EEPROM Config Porta = Input Kn1 Alias Pina.3 Kn2 Alias Pina.2 Cls Cursor Off Noblink Data_izm = 0 Dsp = 1 Uts = "0" Road = 0 Flag = 0 Tputi_h = 0 Tputi_m = 0 Tputi_s = 0 If Kn2 = 0 Then 'если во время подачи питания нажата кнопка 2 то стираем все одометры и прочее Cls Locate 2 , 1 : Lcd " Erase ODO" Ee_road_all = 0 Ee_road_day = 0 Day = "01" Ee_road_last = 0 Ee_tputi_h = 0 Ee_tputi_m = 0 Ee_max_speed = 0 Ee_moto_m = 0 Ee_moto_h = 0 Ee_moto_s = 0 Wait 1 End If 'чтение накопленных данных из EEPROM Road_last = Ee_road_last Road_all = Ee_road_all Road_day = Ee_road_day Max_speed = Ee_max_speed Tputi_h_last = Ee_tputi_h Tputi_m_last = Ee_tputi_m Day = Ee_day Moto_m = Ee_moto_m Moto_h = Ee_moto_h Moto_s = Ee_moto_s 'заставка Cls Locate 1 , 1 : Lcd " " Locate 2 , 1 : Lcd " Boat Comp V1.0 " Locate 3 , 1 : Lcd " Y.D.E. 2013 " Locate 4 , 1 : Lcd " " Wait 1 'начало Enable Interrupts Enable Timer0 Enable Aci Start Ac Start Watchdog 'start the watchdog timer 'основной цикл Loop: 'запускаем DS18b20 1wreset ' reset the bus 1wwrite &HCC ' skip rom 1wwrite &H44 ' Convert T Call Wait_for_string( "$GPGGA,") ' вызов подпрограмы ожидающий строку, начинающуюся с $GPGGA, Sat = Read_string() 'разбриаем строку $GPGGA на состовляющие Sat = Read_string() 'пропускаем ненужные используя одну переменную Sat = Read_string() ' Sat = Read_string() ' Sat = Read_string() ' Gpsfix = Read_string() 'если 0 то положение не определено Sat = Read_string() ' Количество задействованых спутников Call Wait_for_string( "$GPRMC,") ' вызов подпрограмы ожидающий строку, начинающуюся с $GPRMC, 'разбриаем строку $GPRMC на состовляющие Uts = Read_string() 'время по гринвичу Av = Read_string() Lat = Read_string() 'широта Leng = Len(lat) - 1 ' Lat = Left(lat , Leng) ' Ns = Read_string() 'северная южная Leng = Len(ns) - 1 ' Ns = Left(ns , Leng) ' Lon = Read_string() 'долгота Leng = Len(lon) - 1 ' Lon = Left(lon , Leng) ' Ew = Read_string() 'западная восточная Leng = Len(ew) - 1 ' Ew = Left(ew , Leng) ' Spd = Read_string() 'скорость в милях в час Leng = Len(spd) - 1 ' Spd = Left(spd , Leng) ' Crs = Read_string() ' курс Leng = Len(crs) - 1 ' Crs = Left(crs , Leng) ' Da4 = Read_string() 'дата Da4 = Left(da4 , 6) ' Spd2 = Val(spd) Spd2 = Spd2 * 1.852 'пересчитываем скорость из миль в км/ч If Gpsfix = "0" Then Spd2 = 0 'если нет фиксации GPS то обнуляем скорость потому как она не верна Speed = Int(spd2) 'отбрасываем дробную часть для лучшего отображения If Speed > Max_speed Then Max_speed = Speed 'запоминаем максимальную скорость Spd3 = Spd2 / 3600 ' путь пройденый за 1 секунду If Spd2 > 2 Then 'если скорость меньше 2 км/ч одометры не задействованы Road = Road + Spd3 Road_day = Road_day + Spd3 'судочный пробег Road_all = Road_all + Spd3 'суммарный пройденый путь End If Hhs = Left(uts , 2) 'выделяем часы минуты Hh = Val(hhs) Mm = Mid(uts , 3 , 2) Hh = Hh + 4 'коректировка времени на часовой пояс (Медведевская Москва +4 часа в данном случае) If Hh > 23 Then Hh = Hh - 24 T_day = Left(da4 , 2) 'выделяем из даты день If Gpsfix <> "0" Then If Day <> T_day Then 'при смене суток обнуляем данные суточного пробега Day = T_day Ee_day = Day Ee_road_day = 0 Road_day = 0 End If End If If Gpsfix <> "0" And Speed > 3 Then Data_izm = 1 'если есть связь и скорость больше 3 км/ч даем разрешение на сохранение данных в eeprom Flag = Not Flag 'изменяется каждую секунду If Flag = 1 Then 'мигание точек в часах Dot = ":" Else Dot = " " End If '******** счетчик времени в пути ********* If Spd2 > 2 Then Incr Tputi_s 'Incr Tputi_s If Tputi_s > 59 Then Incr Tputi_m Tputi_s = 0 End If If Tputi_m > 59 Then Incr Tputi_h Tputi_m = 0 End If '************** Напряжёметр *************** U = Getadc(4) 'читаем АЦП Shift U , Right , 2 'из 12 бит делаем 8 'U = U / 2 Um = U Mod 10 : Uh = U - Um : Uh = Uh / 10 ' выделяем десятые доли вольта '**************************************' 'читаем DS18b20 1wreset 'reset 1wwrite &HCC 'пропуск пзу 1wwrite &HBE 'чтение памяти For I = 1 To 9 Ar(i) = 1wread() 'place into array Next T = 0 'преобразование температуры T = Makeint(ar(1) , Ar(2)) T = T * 10 T = T / 16 I = T Mod 10 : T = T - I : T = T / 10 If I < 0 Then I = I * -1 If T > T_control Then Dsp = 5 'контроль перегрева двигателя Reset Watchdog If Dsp1 <> Dsp Then 'переключатель экранов Dsp1 = Dsp Cls Kn_on = 1 End If ' тахометр Tah = Timer1 Tah = Tah / 16.6 'переводим герцы в обороты в минуту Tah = Tah / Delitel 'делитель количество импульсов на один оборот двигателя '****** счетчик моточасов ******** If Tah > 0.2 Then 'если обороты больше 200 то считаем моточасы Incr Moto_s If Moto_s > 59 Then Incr Moto_m Moto_s = 0 End If If Moto_m > 59 Then Incr Moto_h Moto_m = 0 End If End If '******* Экран перегрева **************** If Dsp = 5 Then If Flag = 1 Then 'мигаем страшными словами Locate 1 , 1 : Lcd "####################" Locate 2 , 1 : Lcd "#### WARNING!!! ####" Locate 3 , 1 : Lcd "#### t " ; T ; "." ; I ; " C " Locate 3 , 16 : Lcd " ####" Locate 4 , 1 : Lcd "####################" Else Locate 1 , 1 : Lcd " " Locate 2 , 1 : Lcd " WARNING!!! " Locate 3 , 1 : Lcd " t " ; T ; "." ; I ; " C " Locate 3 , 16 : Lcd " " Locate 4 , 1 : Lcd " " End If End If '******** Главный экран ************************* If Dsp = 1 Then ' тахометр If Tah > 0.1 Then Locate 2 , 1 : Lcd "Tah " ; Fusing(tah , "#.#") ; " Rpm " Else Locate 2 , 1 : Lcd " " End If Timer1 = 0 'дата и кол-во спутников If Gpsfix <> "0" Then Locate 1 , 1 : Lcd Chr(0) ; Sat ; " " ; Left(da4 , 2) ; "/" ; Mid(da4 , 3 , 2) ; "/" ; Right(da4 , 2) ; " " Else Locate 1 , 1 : Lcd "Connecting... " End If 'часы If Hh < 10 Then Locate 1 , 16 : Lcd "0" ; Hh ; Dot ; Mm Else Locate 1 , 16 : Lcd Hh ; Dot ; Mm End If 'температура Locate 2 , 16 If T = 0 Then Lcd " " If T < 0 Then Lcd Chr(5) ; T ; " " If T > 0 And T < 10 Then Lcd Chr(5) ; T ; "." ; I ; "C" ' If T >= 10 And T < 100 Then Lcd Chr(5) ; T ; "." ; I ' If T >= 100 Then Lcd Chr(5) ; T ; "C" 'вольтметр If Uh < 11 Then If Flag = 0 Then If Uh >= 10 Then Locate 3 , 16 : Lcd Chr(1) ; Uh ; "." ; Um '; "v" Else Locate 3 , 16 : Lcd Chr(1) ; " " ; Uh ; "." ; Um End If Else Locate 3 , 16 : Lcd " " End If Else If Uh >= 10 Then Locate 3 , 16 : Lcd Chr(1) ; Uh ; "." ; Um '; "v" Else Locate 3 , 16 : Lcd Chr(1) ; " " ; Uh ; "." ; Um End If End If 'скорость Locate 3 , 1 : Lcd "Spd< " ; Speed ; " >km/h " 'одометр Locate 4 , 1 If Road >= 100 Then Lcd "Odo " ; Fusing(road , "####.#") ; "km " If Road >= 10 And Road < 100 Then Lcd "Odo 0" ; Fusing(road , "####.#") ; "km " If Road < 10 Then Lcd "Odo 00" ; Fusing(road , "####.#") ; "km " 'время в пути If Tputi_h < 10 Then Locate 4 , 13 : Lcd "0" ; Tputi_h ; ":" Else Locate 4 , 13 : Lcd Tputi_h ; ":" End If If Tputi_m < 10 Then Locate 4 , 16 : Lcd "0" ; Tputi_m ; ":" Else Locate 4 , 16 : Lcd Tputi_m ; ":" End If If Tputi_s < 10 Then Locate 4 , 19 : Lcd "0" ; Tputi_s Else Locate 4 , 19 : Lcd Tputi_s End If End If '******** экран навигации ************************* If Dsp = 2 Then Locate 1 , 1 : Lcd "CѕyїЅёєё " ; Sat ; " Єёєc " ; Gpsfix ; " " Locate 2 , 1 : Lcd "¬ёp " ; Lat ; " " ; Ns Locate 3 , 1 : Lcd "аo»ґ " ; Lon ; " " ; Ew Locate 4 , 1 : Lcd "CєopocїД " ; Fusing(spd2 , "###.#") ; " Kј/А " End If '******** экран одометров ************************* If Dsp = 3 Then Locate 1 , 1 : Lcd "Max Speed " ; Max_speed ; " km/h " Locate 2 , 1 : Lcd "Last " ; Fusing(road_last , "####.#") ; "km " Locate 3 , 1 : Lcd "Day " ; Fusing(road_day , "####.#") ; "km " Locate 4 , 1 : Lcd "All " ; Fusing(road_all , "####.#") ; "km " If Tputi_h_last < 10 Then Locate 2 , 14 : Lcd "<0" ; Tputi_h_last ; ":" Else Locate 2 , 14 : Lcd "<" ; Tputi_h_last ; ":" End If If Tputi_m_last < 10 Then Locate 2 , 18 : Lcd "0" ; Tputi_m_last ; ">" Else Locate 2 , 18 : Lcd Tputi_m_last ; ">" End If End If '******** экран моточасов ************************* If Dsp = 4 Then Locate 1 , 5 : Lcd "Moto hours " Locate 3 , 1 : Lcd " << " ; Moto_h ; "h " ; Moto_m ; "m " ; Moto_s ; "s >> " End If Goto Loop '------------------------------------------------------ Sub Wait_for_string(byval S As String) As String 'подпрограмма ожидания строки $GPRMC в данных GPS приемника Local Ii As Byte Local Cc As Byte Ii = 1 M1: Cc = Waitkey() If Cc <> Mid(s , Ii , 1) Then Goto M1 Else Incr Ii If Ii > Len(s) Then Goto M2 Goto M1 End If M2: End Sub '------------------------------------------------------ 'подпрограмма "разбора " строки $GPRMC на части Function Read_string() As String Local Cc As Byte Local Ss As String * 14 Ss = "" Do Cc = Waitkey() 'ожидает символ If Cc <> "," Then Ss = Ss + Chr(cc) Loop Until Cc = "," Cc = "" Read_string = Left(ss , 12) End Function End Save_eeprom: Reset Watchdog 'запись текущего пути и времени в EEPROM по выключении питания. Используется ионистор 0.1Ф для резерв питания If Data_izm = 1 Then 'если данные не менялись (gpsfix=0 и скорость<3) тогда не пишем Ee_road_last = Road Ee_road_all = Road_all Ee_road_day = Road_day Ee_tputi_h = Tputi_h Ee_tputi_m = Tputi_m Ee_max_speed = Max_speed Data_izm = 0 End If Ee_moto_m = Moto_m Ee_moto_h = Moto_h Ee_moto_s = Moto_s Return Pulse: 'кнопки If Kn1 = 0 And Kn_on = 1 Then Incr Dsp Kn_on = 0 If Dsp > 4 Then Dsp = 1 End If Return End