Program do obsługi urządzenia jest praktycznie gotowy. Szacuję jego gotowość na 95%.
Odczyt GPS-u zrealizowałem ostatecznie za pomocą biblioteki TinyGPS napisany przez Mikala Harta.
Wysyłanie ramek APRS realizowane przez biblioteką QAPRS stworzoną przez kolegę Łukasza SQ5RWU.
W wolnej chwili postaram się spiąć wszystko włącznie z radiem na płytce stykowej i sprawdzić działanie całości.
Jeśli ktoś znalazłby chwilę będę wdzięczny za przeanalizowanie kodu i ewentualne komentarze (szczególnie te krytyczne, które pomogą usprawnić urządzenie
)
Kod:
#include <Arduino.h>
#include "ArduinoQAPRS.h"
#include <SoftwareSerial.h>
#include <EEPROM.h>
#include <TinyGPS.h>
#include <string.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
int year, state = 0;
byte month, day, hour, minute, second, hundredths;
float flat, flon;
unsigned long time,age;
unsigned long tim_time = millis() + 1000; // Time display time definition
unsigned long pos_time = millis() + 2000; // Position display time definition
unsigned long dat_time = millis() + 3000; // APRS data display time definition
char pipe_array[10];
char from_addr[10];
char dest_addr[10];
char relays[10];
char aprs_icon[2];
char data2[60];
char massage[20];
String aprs_data="", data="", icon;
char buffor[250];
TinyGPS gps;
SoftwareSerial nss(3, 4); // Gps serial port declaration
SoftwareSerial bt(5,6); // Bluetooth serial port declaration
static bool feedgps();
static void print_float(float val, float invalid, int len, int prec);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);
void setup()
{
Serial.begin(115200);
nss.begin(9600);
bt.begin(9600);
lcd.begin(16,2);
int a=0;
for (int i=0; i <= 250; i++) buffor[i] = EEPROM.read(i); //Eeeporm data read
aprs_data = buffor;
parse_aprs_data();
Serial.println(from_addr);
Serial.println(dest_addr);
Serial.println(relays);
Serial.println(aprs_icon);
Serial.println(massage);
pinMode(2, INPUT);
nss.listen();
QAPRS.init(12,13);
}
void loop()
{
time = millis();
if (digitalRead(2) == LOW) // If bluetooth is not paired - read data form GPS reciver
{
gps_pos(gps);
gps_date(gps);
int l= minute % 5; // Send APRS frame every 5 minutes
if ((l == 0) && (second >=0) && second <= 2) aprs_send();
if (time >= tim_time) // Every 1, 4, 7 second display time on LCD
{
print_date();
print_date_lcd();
tim_time = time + 3000;
}
if (time >= pos_time) // Every 2, 5, 8 second display location data on LCD
{
print_pos();
print_pos_lcd();
pos_time = time + 3000;
}
if (time >= dat_time) // Every 3, 6, 9 second display APRS data on LCD
{
Serial.println(buffor);Serial.println();
print_dat_lcd();
dat_time = time + 3000;
}
}
while (digitalRead(2) == HIGH) //If bluetooth is paired - enter programming mode
{
bt.listen();
while (bt.available()) data += char(bt.read());
if (data != "")
{
Serial.println(data);
aprs_data = data;
data = "";
aprs_data.toCharArray(buffor,250);
for (int i = 0; i <= strlen(buffor);i++) EEPROM.write(i,buffor[i]); // Write data to Eeprom
}
tim_time = millis() + 1000;
pos_time = millis() + 2000;
dat_time = millis() + 3000;
parse_aprs_data();
}
nss.listen();
feedgps();
}
static void gps_pos(TinyGPS &gps) //encode position form GPS
{
gps.f_get_position(&flat, &flon, &age);
feedgps();
}
static void print_pos() //Print position on Serial
{
Serial.println(flat,5);
Serial.println(flon,5);
Serial.println();
}
static void print_pos_lcd() //Display position on LCD
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("LAT : ");lcd.print(flat,5);lcd.print("N");
lcd.setCursor(0,1);
lcd.print("LON : ");lcd.print(flon,5);lcd.print("E");
}
static void print_dat_lcd() // Display APRS data on LCD
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(from_addr);lcd.print(" | ");lcd.print(dest_addr);
lcd.setCursor(0,1);
lcd.print(relays);lcd.print(" | ");lcd.print(aprs_icon);
}
static void gps_date(TinyGPS &gps) // Read date data form GPS
{
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
}
static void print_date() // Print date on Serial
{
if (age == TinyGPS::GPS_INVALID_AGE)
{
Serial.println("******* ******* ");
Serial.println();
}
else
{
char sz[32];
sprintf(sz, "%02d/%02d/%02d", month, day, year);
Serial.println(sz);
sprintf(sz, "%02d:%02d:%02d",hour+2, minute, second);
Serial.println(sz);
Serial.println();
}
feedgps();
}
static void print_date_lcd() // Print date on LCD
{
lcd.clear();
lcd.setCursor(2,0);
char sz[32];
sprintf(sz, "%02d/%02d/%02d", month, day, year);
lcd.print("LOC : ");lcd.print(sz);
lcd.setCursor(2,1);
sprintf(sz, "%02d:%02d:%02d",hour+2, minute, second);
lcd.print("DATE: ");lcd.print(sz);
}
static bool feedgps() // Read GPS data
{
while (nss.available())
{
if (gps.encode(nss.read())) return true;
}
return false;
}
static void parse_aprs_data() // Parse APRS data
{
int a=0;
for (int i=0; i <= 250; i++)
{
if (buffor[i] == '|')
{
pipe_array[a] = i;
a = a++;
}
}
for (int i = 0; i <= pipe_array[0]-1 ; i++) from_addr[i] = buffor[i];
for (int i = pipe_array[0]+1; i <= pipe_array[1]-1; i++) dest_addr[i-pipe_array[0]-1] = buffor[i];
for (int i = pipe_array[1]+1; i <= pipe_array[2]-1; i++) relays[i-pipe_array[1]-1] = buffor[i];
for (int i = pipe_array[2]+1; i <= pipe_array[3]-1; i++) aprs_icon[i-pipe_array[2]-1] = buffor[i];
for (int i = pipe_array[3]+1; i <= pipe_array[4]-1; i++) massage[i-pipe_array[3]-1] = buffor[i];
}
static void parse_aprs_loc() // Parse GPS position for APRS
{
memset(data2, 0, sizeof(data2));
char buf[10];
dtostrf(flat*100,7,2,buf);
strcat(data2,"=");
strcat(data2,buf);
strcat(data2,"N/0");
dtostrf(flon*100,7,2,buf);
strcat(data2,buf);
strcat(data2,"E");
strcat(data2,aprs_icon);
strcat(data2," ");
strcat(data2,massage);
}
static void aprs_send() // Send APRS packet to radio
{
lcd.setCursor(0,0);
lcd.print(" SEND APRS DATA ");
lcd.setCursor(0,1);
lcd.print(" ");
parse_aprs_loc();
Serial.println(data2);
QAPRS.send(from_addr, '0', dest_addr, '0', relays, data2);
tim_time = millis() + 1000;
pos_time = millis() + 2000;
dat_time = millis() + 3000;
}
Dodatkowo do obsługi systemu napisałem prostą aplikację na Androida pozwalającą na programowanie urządzenia przy pomocy telefonu lub tabletu (wymagana komunikacja bluetooth).
Aplikacja powstała przy użyciu - darmowego, on-linowego
MIT App Inventor 2
Projekt programu w formaci *.aia - pozwala zaimportować projekt do MIT App Inventor 2
Aplikacja na ANDROIDa w formacie *.apk
Testy końcowe prototypu planowane są na ten tydzień.
W związku z tym, że docelowo projekt ma być przeniesiony z Arduino na specjalnie zaprojektowaną płytkę z ATmegą 328 testuje podłączenie przez serial do terminala (chciałbym, aby serial był swoistym logiem pracy urządzenia)
Jako terminala używam putty - ustawiłem Serial na 115200,8,1,N i po podłączeniu dostaje dane w formie absolutnie nieczytelnej
Czy ktoś mi podpowie co może powodować taki problem?