Porównaj commity

...

14 Commity
ary3 ... master

Autor SHA1 Wiadomość Data
Michal Fratczak 5be2df2e68 PDF of schematic 2023-10-12 22:18:56 +02:00
Michal Fratczak 42cb4efc45 Added PCB readme 2020-12-14 09:40:28 +01:00
Michal 546eed4244
Update Readme.md 2020-10-29 22:13:24 +01:00
Michal Fratczak 1127777f86 Stop camera on GPS fix loss. 2020-08-27 22:36:44 +01:00
Michal Fratczak 43a409a0fb hot bugfix to camera.py 2020-08-27 21:48:10 +01:00
Michal Fratczak b6bce14496 camera: disable VIDEO in kLanded state. Send hiRes 2020-08-27 21:29:56 +01:00
Michal Fratczak cb6bb631e2 Improve nmea_t type and fix altitude not being recorded. Adjust flight state logic. 2020-08-25 20:42:23 +01:00
Michal Fratczak 1d7058455b Merge branch 'master' of https://github.com/ogre/pizero_tracker 2020-08-14 00:11:07 +02:00
Michal Fratczak 206e484462 Track current nmea and last valid nmea.
Transmit current, even if not valid.
2020-08-14 00:10:52 +02:00
Michal Fratczak 8f6d03f1b7 Readme upd 2020-07-25 22:53:16 +01:00
Michal Fratczak 15c2b81d6e Merge branch 'master' of https://github.com/ogre/pizero_tracker 2020-07-25 22:46:20 +01:00
Michal Fratczak cf2317fe6a Add tracker.cfg 2020-07-23 22:58:07 +01:00
Michal Fratczak 6ffcfdb1cd wrong case in include. readme update. 2020-07-23 21:30:58 +01:00
Michal Fratczak 285a2bf80a PCB: move reg away from corner hole 2020-07-22 22:31:15 +01:00
15 zmienionych plików z 263 dodań i 118 usunięć

Wyświetl plik

@ -1,6 +1,6 @@
## I2C
You need to use software driver to I2c, and therefore, disable bluetooth. This is for rPI 3 and up.
You need to use software driver to I2C, and therefore, disable bluetooth. This is for rPI 3 and up.
[https://raspberrypi.stackexchange.com/questions/45570/how-do-i-make-serial-work-on-the-raspberry-pi3-or-later-model]
@ -19,26 +19,46 @@ dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3
```
dependencies
## Dependencies
SSDV:
git submodule update --init --recursive
---
sudo apt-get install libboost-program-options-dev
---
git clone https://github.com/zeromq/libzmq.git
build with cmake
---
git clone https://github.com/zeromq/cppzmq.git
build with cmake
---
http://abyz.me.uk/rpi/pigpio/download.html
```
wget https://github.com/joan2937/pigpio/archive/master.zip
unzip master.zip
cd pigpio-master
make
sudo make install
```
---
pip3 install zmq exifread picamera psutil
sudo apt-get install imagemagick
run on one thread:
## Run on one thread:
```
taskset -c 1 ./tracker
```
## MTX2 datasheet
http://www.radiometrix.com/files/additional/mtx2.pdf

Wyświetl plik

@ -173,20 +173,24 @@ def SetCameraExif(camera, state):
def StateLoop(port):
'''
query tracker over ZMQ
ask for: nmea_current, dynamics, flight_state
save in global STATE dictionary
'''
REQUEST_TIMEOUT = 3000
REQUEST_RETRIES = 1e30
SERVER_ENDPOINT = "tcp://localhost:" + str(port)
global STATE
print("Connecting to " + SERVER_ENDPOINT)
context = zmq.Context(1)
client = context.socket(zmq.REQ)
client.connect(SERVER_ENDPOINT)
poll = zmq.Poller()
poll.register(client, zmq.POLLIN)
query_msgs = ['nmea', 'dynamics', 'flight_state']
query_msgs = ['nmea_current', 'dynamics', 'flight_state']
retries_left = REQUEST_RETRIES
while THREADS_RUN and retries_left:
@ -231,7 +235,6 @@ def StateLoop(port):
context.term()
def SSDV_DeliverLoop(callsign, out_ssdv_path, res):
'''
picks last image from PHOTO_ARR, converts to SSDV and copies to output
@ -251,6 +254,7 @@ def SSDV_DeliverLoop(callsign, out_ssdv_path, res):
time.sleep(5)
if not PHOTO_ARR:
print('SSDV_DeliverLoop - PHOTO_ARR empty.')
continue
if os.path.isfile(out_ssdv_path):
@ -270,7 +274,11 @@ def SSDV_DeliverLoop(callsign, out_ssdv_path, res):
pass
def next_path(i_base, ext = ''): # get next subdir/subfile
def next_path(i_base, ext = ''):
'''
for a directory filled with subdirs or files named like: 000001, 000002, 000003
get next dir/file that does not exist yet
'''
if ext and ext[0] != '.':
ext = '.' + ext
i = 1
@ -313,39 +321,67 @@ def CameraLoop(session_dir, opts):
global PHOTO_ARR
snapshot_time = datetime.fromtimestamp(0)
hires_photo_time = datetime.fromtimestamp(0)
alt = 0
dAlt = 0
dAltAvg = 0
global THREADS_RUN
while(THREADS_RUN):
# camera can cause interference to GPS resulting in FIX loss
# monitor FIX age and disable camera for 5 minutes
if 'nmea_current' in STATE and 'fixAge' in STATE['nmea_current']:
fixage = int( STATE['nmea_current']['fixAge'] )
if fixage > 180:
print('GPS FIX lost. Stop Camera and wait.')
CAMERA.stop_preview()
while fixage > 180:
print('fixage', fixage)
time.sleep(5)
fixage = int( STATE['nmea_current']['fixAge'] )
print("GPS fix reacquired. Waiting 5 minutes to start camera.")
time.sleep(5 * 60)
disk_use_percent = int( psutil.disk_usage('/').percent )
if disk_use_percent > 95:
CAMERA.stop_preview()
print("Free disk space left: ", disk_use_percent, '% . Waiting.')
CAMERA.stop_preview()
time.sleep(60)
continue
if 'flight_state' in STATE and STATE['flight_state']['flight_state'] == 'kLanded':
CAMERA.stop_preview()
print("flight_state::klanded - stop camera and wait.")
CAMERA.stop_preview()
time.sleep(60)
continue
CAMERA.start_preview()
# full res photo
print("Photo HI")
CAMERA.resolution = (3280, 2464)
SetCameraExif(CAMERA, STATE)
CAMERA.annotate_text = ''
CAMERA.capture( next_path(photo_hi_dir, 'jpeg'))
# make full res photo before recording next clip. not more often than 60 secs.
hires_photo_path = None
if seconds_since(hires_photo_time) > 60:
print("Photo HI")
CAMERA.start_preview()
CAMERA.resolution = (2592 , 1944 ) # v1
# CAMERA.resolution = (3280, 2464) # v2
SetCameraExif(CAMERA, STATE)
CAMERA.annotate_text = ''
hires_photo_path = next_path(photo_hi_dir, 'jpeg')
CAMERA.capture( hires_photo_path )
CAMERA.stop_preview()
hires_photo_time = utcnow()
# do not record video in standby mode
# instead send hires_photo_path to SSDV
if 'flight_state' in STATE and STATE['flight_state']['flight_state'] == 'kStandBy':
CAMERA.stop_preview()
print("flight_state::kStandBy - skip video recording. Send HiRes to SSDV.")
PHOTO_ARR.append( hires_photo_path )
time.sleep(60)
continue
# video clip
print("Video")
video_duration_secs = int( opts['cam_video_dur'] )
snapshot_interval_secs = int( opts['cam_snapshot_interval'] )
CAMERA.start_preview()
CAMERA.resolution = (1280, 720)
CAMERA.start_recording( next_path(video_dir, 'h264'))
@ -355,12 +391,23 @@ def CameraLoop(session_dir, opts):
if not THREADS_RUN:
break
disk_use_percent = int( psutil.disk_usage('/').percent )
if disk_use_percent > 95:
fixage = 0
if 'nmea_current' in STATE and 'fixAge' in STATE['nmea_current']:
fixage = int( STATE['nmea_current']['fixAge'] )
if fixage > 180:
print("GPS FIX lost - stop camera.")
CAMERA.stop_preview()
print("Free disk low - abort camera.")
break
disk_use_percent = int( psutil.disk_usage('/').percent )
if disk_use_percent > 95:
print("Free disk low - abort camera.")
CAMERA.stop_preview()
break
alt = 0
dAlt = 0
dAltAvg = 0
if 'dynamics' in STATE and 'alt' in STATE['dynamics']:
alt = STATE['dynamics']['alt']['val']
dAlt = STATE['dynamics']['alt']['dVdT']
@ -372,9 +419,10 @@ def CameraLoop(session_dir, opts):
if seconds_since(snapshot_time) > snapshot_interval_secs:
print("Photo LO")
PHOTO_ARR.append( next_path(photo_lo_dir, 'jpg') )
CAMERA.capture( PHOTO_ARR[-1] , use_video_port = True )
img_path = next_path(photo_lo_dir, 'jpg')
CAMERA.capture( img_path , use_video_port = True )
snapshot_time = utcnow()
PHOTO_ARR.append( img_path )
time.sleep(1)
CAMERA.stop_recording()

3
pcb/Readme.md 100644
Wyświetl plik

@ -0,0 +1,3 @@
IMPORTANT:
Powering to 3.3V from a regulator does not work here.
Instead, use 5V regulator and connect to 5V pin.

Wyświetl plik

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE eagle SYSTEM "eagle.dtd">
<eagle version="9.4.2">
<eagle version="9.6.2">
<drawing>
<settings>
<setting alwaysvectorfont="no"/>
@ -1629,7 +1629,7 @@ design rules under a new name.</description>
<param name="PrefDir.13" value="0"/>
<param name="PrefDir.14" value="0"/>
<param name="PrefDir.15" value="0"/>
<param name="PrefDir.16" value="0"/>
<param name="PrefDir.16" value="a"/>
<param name="cfVia" value="8"/>
<param name="cfNonPref" value="5"/>
<param name="cfChangeDir" value="2"/>
@ -1704,9 +1704,9 @@ design rules under a new name.</description>
</pass>
</autorouter>
<elements>
<element name="3V3_REGULATOR" library="pinhead" library_urn="urn:adsk.eagle:library:325" package="1X03" package3d_urn="urn:adsk.eagle:package:22458/2" value="3.3" x="27.94" y="11.43" smashed="yes">
<attribute name="POPULARITY" value="92" x="53.34" y="-36.83" size="1.778" layer="27" display="off"/>
<attribute name="VALUE" x="31.75" y="9.525" size="1.27" layer="27"/>
<element name="3V3_REGULATOR" library="pinhead" library_urn="urn:adsk.eagle:library:325" package="1X03" package3d_urn="urn:adsk.eagle:package:22458/2" value="3.3" x="29.94" y="11.43" smashed="yes">
<attribute name="POPULARITY" value="92" x="55.34" y="-36.83" size="1.778" layer="27" display="off"/>
<attribute name="VALUE" x="31.75" y="13.525" size="1.27" layer="27"/>
</element>
<element name="BATT" library="pinhead" library_urn="urn:adsk.eagle:library:325" package="1X02" package3d_urn="urn:adsk.eagle:package:22435/2" value="5" x="21.59" y="22.86" smashed="yes" rot="R90">
<attribute name="POPULARITY" value="98" x="69.85" y="67.31" size="1.778" layer="27" rot="R90" display="off"/>
@ -1780,9 +1780,6 @@ design rules under a new name.</description>
<wire x1="50.8" y1="29.21" x2="54.61" y2="33.02" width="0.508" layer="16"/>
<wire x1="43.815" y1="29.21" x2="50.8" y2="29.21" width="0.508" layer="16"/>
<wire x1="54.61" y1="33.02" x2="54.77" y2="33.39" width="0.508" layer="16"/>
<wire x1="27.94" y1="22.86" x2="27.94" y2="11.43" width="0.508" layer="16"/>
<wire x1="23.495" y1="22.86" x2="27.94" y2="22.86" width="0.508" layer="16"/>
<wire x1="22.225" y1="24.13" x2="23.495" y2="22.86" width="0.508" layer="16"/>
<wire x1="72.39" y1="33.02" x2="68.58" y2="29.21" width="0.508" layer="16"/>
<wire x1="68.58" y1="29.21" x2="67.31" y2="27.94" width="0.508" layer="16"/>
<wire x1="72.39" y1="33.02" x2="72.55" y2="33.39" width="0.508" layer="16"/>
@ -1799,19 +1796,21 @@ design rules under a new name.</description>
<wire x1="59.055" y1="29.21" x2="55.245" y2="33.02" width="0.508" layer="16"/>
<wire x1="68.58" y1="29.21" x2="59.055" y2="29.21" width="0.508" layer="16"/>
<wire x1="55.245" y1="33.02" x2="54.77" y2="33.39" width="0.508" layer="16"/>
<wire x1="29.6672" y1="16.6624" x2="29.6672" y2="11.7856" width="0.508" layer="16"/>
<wire x1="22.352" y1="23.9776" x2="29.6672" y2="16.6624" width="0.508" layer="16"/>
<wire x1="29.6672" y1="11.7856" x2="29.94" y2="11.43" width="0.508" layer="16"/>
<wire x1="22.352" y1="23.9776" x2="21.59" y2="24.13" width="0.508" layer="16"/>
<polygon width="0.1524" layer="1">
<vertex x="13.97" y="41.91"/>
<vertex x="13.97" y="6.35"/>
<vertex x="83.82" y="6.35"/>
<vertex x="85.09" y="7.62"/>
<vertex x="85.09" y="41.91"/>
<vertex x="15" y="42"/>
<vertex x="15" y="7"/>
<vertex x="82" y="7"/>
<vertex x="82" y="42"/>
</polygon>
<polygon width="0.1524" layer="16">
<vertex x="13.97" y="41.91"/>
<vertex x="13.97" y="6.35"/>
<vertex x="83.82" y="6.35"/>
<vertex x="85.09" y="7.62"/>
<vertex x="85.09" y="41.91"/>
<vertex x="14" y="43"/>
<vertex x="14" y="6"/>
<vertex x="83" y="6"/>
<vertex x="83" y="43"/>
</polygon>
</signal>
<signal name="SDA">
@ -1926,21 +1925,24 @@ design rules under a new name.</description>
<wire x1="44.45" y1="24.765" x2="42.545" y2="24.765" width="0.508" layer="16"/>
<wire x1="45.085" y1="24.765" x2="48.26" y2="27.94" width="0.508" layer="16"/>
<wire x1="44.45" y1="24.765" x2="45.085" y2="24.765" width="0.508" layer="16"/>
<wire x1="30.48" y1="21.59" x2="30.48" y2="11.43" width="0.508" layer="16"/>
<wire x1="39.37" y1="21.59" x2="34.29" y2="21.59" width="0.508" layer="16"/>
<wire x1="34.29" y1="21.59" x2="30.48" y2="21.59" width="0.508" layer="16"/>
<wire x1="34.29" y1="21.59" x2="34.29" y2="24.13" width="0.508" layer="16"/>
<wire x1="34.29" y1="24.13" x2="34.29" y2="26.67" width="0.508" layer="16"/>
<wire x1="24.765" y1="24.13" x2="24.765" y2="33.02" width="0.508" layer="16"/>
<wire x1="34.29" y1="24.13" x2="24.765" y2="24.13" width="0.508" layer="16"/>
<wire x1="24.765" y1="33.02" x2="24.29" y2="33.39" width="0.508" layer="16"/>
<wire x1="32.512" y1="19.9136" x2="32.512" y2="11.7856" width="0.508" layer="16"/>
<wire x1="34.1376" y1="21.5392" x2="32.512" y2="19.9136" width="0.508" layer="16"/>
<wire x1="32.512" y1="11.7856" x2="32.48" y2="11.43" width="0.508" layer="16"/>
<wire x1="34.1376" y1="21.5392" x2="34.29" y2="21.59" width="0.508" layer="16"/>
</signal>
<signal name="5V">
<contactref element="3V3_REGULATOR" pad="1"/>
<contactref element="BATT" pad="1"/>
<wire x1="25.4" y1="20.955" x2="25.4" y2="11.43" width="0.508" layer="16"/>
<wire x1="22.225" y1="20.955" x2="25.4" y2="20.955" width="0.508" layer="16"/>
<wire x1="21.59" y1="21.59" x2="22.225" y2="20.955" width="0.508" layer="16"/>
<wire x1="21.9456" y1="17.0688" x2="21.9456" y2="21.5392" width="0.508" layer="1"/>
<wire x1="27.2288" y1="11.7856" x2="21.9456" y2="17.0688" width="0.508" layer="1"/>
<wire x1="21.9456" y1="21.5392" x2="21.59" y2="21.59" width="0.508" layer="1"/>
<wire x1="27.2288" y1="11.7856" x2="27.4" y2="11.43" width="0.508" layer="1"/>
</signal>
<signal name="N$7">
<contactref element="R5" pad="2"/>

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -1,25 +1,25 @@
EAGLE AutoRouter Statistics:
Job : /home/mfratczak/dev/Eagle/HabTrackerPiZero/HabTrackerPiZero_Shield_v304.brd
Start at : 21:19:28 (15.01.2020)
End at : 21:19:30 (15.01.2020)
Elapsed time : 00:00:01
Signals : 13 RoutingGrid: 16 mil Layers: 1
Connections : 31 predefined: 28 ( 0 Vias )
Router memory : 104140
Passname : TopRouter Route Optimize1 Optimize2 Optimize3 Optimize4
Time per pass : 00:00:01 00:00:00 00:00:00 00:00:00 00:00:00 00:00:00
Number of Ripups : 0 0 0 0 0 0
max. Level : 0 0 0 0 0 0
max. Total : 0 0 0 0 0 0
Routed : 3 3 3 3 3 3
Vias : 0 0 0 0 0 0
Resolution : 100.0 % 100.0 % 100.0 % 100.0 % 100.0 % 100.0 %
Final : 100.0% finished
EAGLE AutoRouter Statistics:
Job : D:/dev/Projects/pizero_tracker/pizero_tracker/pcb/eagle/HabTrackerPiZero_Shield.brd
Start at : 22:29:04 (7/22/2020)
End at : 22:29:09 (7/22/2020)
Elapsed time : 00:00:02
Signals : 13 RoutingGrid: 16 mil Layers: 2
Connections : 31 predefined: 28 ( 0 Vias )
Router memory : 208280
Passname : TopRouter Route Optimize1 Optimize2 Optimize3 Optimize4
Time per pass : 00:00:02 00:00:00 00:00:00 00:00:00 00:00:00 00:00:00
Number of Ripups : 0 0 0 0 0 0
max. Level : 0 0 0 0 0 0
max. Total : 0 0 0 0 0 0
Routed : 3 3 3 3 3 3
Vias : 0 0 0 0 0 0
Resolution : 100.0 % 100.0 % 100.0 % 100.0 % 100.0 % 100.0 %
Final : 100.0% finished

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -32,6 +32,7 @@ private:
GLOB& operator=( const GLOB& ) = delete; // non copyable
std::atomic<nmea_t> nmea_; // GPS data
std::atomic<nmea_t> nmea_last_valid_; // GPS data - last valid
std::chrono::steady_clock::time_point gps_fix_timestamp_;
// sensors dynamics
@ -73,8 +74,16 @@ public:
dynamics_t dynamics_get(const std::string& name) const;
std::vector<std::string> dynamics_keys() const; // names in dynamics_
void nmea_set(const nmea_t& in_nmea) { get().nmea_ = in_nmea; }
nmea_t nmea_get() { nmea_t ret = get().nmea_; return ret; }
void nmea_set(const nmea_t& in_nmea) {
get().nmea_ = in_nmea;
if(in_nmea.valid()) {
get().nmea_last_valid_ = in_nmea;
get().gps_fix_now();
}
}
nmea_t nmea_current() { nmea_t ret = get().nmea_; return ret; }
nmea_t nmea_last_valid() { nmea_t ret = get().nmea_last_valid_; return ret; }
void gps_fix_now() { gps_fix_timestamp_ = std::chrono::steady_clock::now(); }
int gps_fix_age() const { return (std::chrono::steady_clock::now() - gps_fix_timestamp_).count() / 1e9; }

Wyświetl plik

@ -5,7 +5,7 @@
#include <vector>
#include <iostream>
#include <fstream>
#include "glob.h"
#include "GLOB.h"
#include <boost/program_options.hpp>

Wyświetl plik

@ -7,7 +7,6 @@
#include <algorithm>
// utc_seconds is HHMMSS converted to seconds. return true if sample was accepted
void dynamics_t::add(const tp timestamp, const float val)
{
val_ = val;

Wyświetl plik

@ -82,7 +82,7 @@ public:
bool initialised() const { return initialised_; }
void add(const tp timestamp, const float val); // utc_seconds is HHMMSS converted to seconds. return true if sample was accepted
void add(const tp timestamp, const float val);
float val() const { return val_; }
float min() const { return val_min_; }

Wyświetl plik

@ -78,8 +78,16 @@ std::string CRC(std::string i_str)
zmq::message_t make_zmq_reply(const std::string& i_msg_str)
{
auto& G = GLOB::get();
if(i_msg_str == "nmea") {
std::string reply_str = G.nmea_get().json();
if(i_msg_str == "nmea_current") {
std::string reply_str = G.nmea_current().json();
reply_str.pop_back();
reply_str += ",'fixAge':" + std::to_string(G.gps_fix_age()) + "}";
zmq::message_t reply( reply_str.size() );
memcpy( (void*) reply.data(), reply_str.c_str(), reply_str.size() );
return reply;
}
else if(i_msg_str == "nmea_last_valid") {
std::string reply_str = G.nmea_last_valid().json();
reply_str.pop_back();
reply_str += ",'fixAge':" + std::to_string(G.gps_fix_age()) + "}";
zmq::message_t reply( reply_str.size() );
@ -270,21 +278,18 @@ int main1(int argc, char** argv)
LOG.log("nmea.log", nmea_str);
nmea_t current_nmea;
// REUSE LAT,LON,ALT FROM LAST VALID SENTENCE
// if currently parsed NMEA string has valid lat/lon/alt
// they will be stored in current_nmea
// otherwise we keep last valid
const nmea_t valid_nmea = GLOB::get().nmea_get();
current_nmea.lat = valid_nmea.lat;
current_nmea.lon = valid_nmea.lon;
current_nmea.alt = valid_nmea.alt;
if( NMEA_parse(nmea_str.c_str(), current_nmea) /*and current_nmea.valid()*/ ) {
// RMC has no altitude, copy from last known value
if( current_nmea.nmea_msg_type_ == nmea_t::nmea_msg_type_t::kRMC )
current_nmea.alt = GLOB::get().nmea_current().alt;
if( NMEA_parse(nmea_str.c_str(), current_nmea) and current_nmea.valid() ) {
GLOB::get().nmea_set(current_nmea);
GLOB::get().gps_fix_now(); // typical time since uBlox msg read to here is under 1 millisecond
GLOB::get().dynamics_add("alt", std::chrono::steady_clock::now(), current_nmea.alt);
if(current_nmea.valid())
GLOB::get().dynamics_add("alt", std::chrono::steady_clock::now(), current_nmea.alt);
// cout<<C_MAGENTA<<"alt "<<GLOB::get().dynamics_get("alt").str()<<C_OFF<<endl;
}
// else - parse error or no lock (even no time)
}
};
@ -293,7 +298,7 @@ int main1(int argc, char** argv)
auto fake_gps_loop = [uBlox_i2c_fd]() {
cout<<"Using FAKE GPS Coordinates !!!"<<endl;
while(G_RUN) {
const nmea_t valid_nmea = GLOB::get().nmea_get();
const nmea_t valid_nmea = GLOB::get().nmea_current();
nmea_t current_nmea;
current_nmea.lat = valid_nmea.lat;
current_nmea.lon = valid_nmea.lon;
@ -363,7 +368,7 @@ int main1(int argc, char** argv)
this_thread::sleep_for( chrono::seconds(1) );
GLOB::get().runtime_secs_ = chrono::duration_cast<chrono::seconds>(chrono::steady_clock::now() - START_TIME).count();
const nmea_t nmea = GLOB::get().nmea_get();
const nmea_t nmea = GLOB::get().nmea_last_valid();
const auto dist_from_home = calc_gps_distance( nmea.lat, nmea.lon, nmea.alt,
GLOB::get().cli.lat, GLOB::get().cli.lon, 0);
const auto alt = GLOB::get().dynamics_get("alt");
@ -373,14 +378,14 @@ int main1(int argc, char** argv)
if(nmea.valid()) {
if( abs(dist_from_home.dist_line_) < 200 and abs(dAltAvg) <= 3 )
flight_state = flight_state_t::kStandBy;
else if(dAltAvg < -8)
flight_state = flight_state_t::kFreefall;
else if(dAltAvg < -3)
flight_state = flight_state_t::kDescend;
else if(dAltAvg > 3)
flight_state = flight_state_t::kAscend;
else if( abs(dist_from_home.dist_line_) > 2000 and abs(dAltAvg) <= 3 and alt.val() < 2000 )
flight_state = flight_state_t::kLanded;
else if(dAltAvg < -15)
flight_state = flight_state_t::kFreefall;
else if(dAltAvg < 0)
flight_state = flight_state_t::kDescend;
else if(dAltAvg >= 0)
flight_state = flight_state_t::kAscend;
}
// cout<<alt.val()<<" "<<alt.dVdT()<<" "<<alt.dVdT_avg()<<" "<<dist_from_home.dist_line_<<endl;
GLOB::get().flight_state_set( flight_state );
@ -466,14 +471,14 @@ int main1(int argc, char** argv)
stringstream tlmtr_stream;
// Callsign, ID, UTC:
const nmea_t valid_nmea = G.nmea_get();
const nmea_t current_nmea = G.nmea_current();
tlmtr_stream<<G.cli.callsign;
tlmtr_stream<<","<<msg_id;
tlmtr_stream<<","<<valid_nmea.utc;
tlmtr_stream<<","<<current_nmea.utc;
// !! ONLY VALID LAT,LON,ALT ARE BEING SENT. LOOK INTO uBLOX THREAD.
tlmtr_stream<<","<<valid_nmea.lat<<","<<valid_nmea.lon<<","<<valid_nmea.alt;
tlmtr_stream<<","<<valid_nmea.sats<<","<<GLOB::get().gps_fix_age();
tlmtr_stream<<","<<current_nmea.lat<<","<<current_nmea.lon<<","<<current_nmea.alt;
tlmtr_stream<<","<<current_nmea.sats<<","<<GLOB::get().gps_fix_age();
// runtime
tlmtr_stream<<","<<static_cast<int>(GLOB::get().runtime_secs_);

Wyświetl plik

@ -134,6 +134,8 @@ bool NMEA_parse(const char* Buffer, nmea_t& o_nmea)
if (strncmp(Buffer + 3, "GGA", 3) == 0) // Global positioning system fix data
{
o_nmea.nmea_msg_type_ = nmea_t::nmea_msg_type_t::kGGA;
int scanned_positions =
sscanf(Buffer + 7, "%f,%f,%c,%f,%c,%d,%d,%f,%f,%c", &
utc, &lat, &ns, &lon, &ew, &quality, &sats, &hdop, &alt, &alt_units);
@ -175,6 +177,7 @@ bool NMEA_parse(const char* Buffer, nmea_t& o_nmea)
o_nmea.fix_quality = nmea_t::fix_quality_t::kEstimated;
break;
}
return true;
}
else if(scanned_positions > 0 && utc != 0)
@ -191,6 +194,8 @@ bool NMEA_parse(const char* Buffer, nmea_t& o_nmea)
} // GGA
else if (strncmp(Buffer+3, "RMC", 3) == 0)
{
o_nmea.nmea_msg_type_ = nmea_t::nmea_msg_type_t::kRMC;
speedstring[0] = '\0';
coursestring[0] = '\0';
int scanned_positions =
@ -338,8 +343,9 @@ int nmea_t::utc_as_seconds() const
bool nmea_t::valid() const
{
// only one at a time can be valid.
// fix_status is from RMC, fix_quality is from GGA
return fix_status == fix_status_t::kValid
or fix_quality != fix_quality_t::kNoFix;
if(nmea_msg_type_ == nmea_msg_type_t::kGGA and fix_quality != fix_quality_t::kNoFix)
return true;
if(nmea_msg_type_ == nmea_msg_type_t::kRMC and fix_status == fix_status_t::kValid)
return true;
return false;
}

Wyświetl plik

@ -5,26 +5,23 @@
// keep data parsed from GGA __and__ RMC messages
// http://aprs.gids.nl/nmea/#rmc
// http://aprs.gids.nl/nmea/#gga
class nmea_t
{
public:
// fields provided by both GGA and RMC messages:
//
char utc[6] = {'0', '0', '0', '0', '0', '0'}; // HHMMSS
float lat = 0; // degree
float lon = 0; // degree
// GGA message fields:
//
float alt = 0; // meters
float speed_over_ground_mps = 0;
float course_over_ground_deg = 0;
int sats = 0;
enum class fix_status_t : int {
kInvalid=0, // V
kValid=1 // A
};
fix_status_t fix_status = fix_status_t::kInvalid;
enum class fix_quality_t : int {
kNoFix = 0,
kAutonomous = 1,
@ -35,6 +32,25 @@ public:
};
fix_quality_t fix_quality = fix_quality_t::kNoFix;
// RMC message fields:
//
float speed_over_ground_mps = 0;
float course_over_ground_deg = 0;
enum class fix_status_t : int {
kInvalid=0, // V
kValid=1 // A
};
fix_status_t fix_status = fix_status_t::kInvalid;
enum class nmea_msg_type_t : int {
kUnknown = 0,
kGGA = 1,
kRMC = 2
};
nmea_msg_type_t nmea_msg_type_ = nmea_msg_type_t::kUnknown;
std::string str() const;
std::string json() const;

Wyświetl plik

@ -0,0 +1,37 @@
# tracker options
#
callsign = setcallsign
freq = 434.5
baud = 300
port = 6666
ssdv = /tracker/ssdv.bin
logsdir = /tracker/logs/
# number of telemetry packets to send before SSDV packet
msg_num = 3
# launch location
latlonalt = 52.1120009
latlonalt = 19.957789
latlonalt = 100
# enable watchdog
watchdog = 1
# hardware configuration
#
hw_pin_radio_on = 22
hw_radio_serial = /dev/serial0
#pi4
#hw_ublox_device = /dev/i2c-7
#pi0
hw_ublox_device = /dev/i2c-3
# camera
#
cam_dir = /tracker/camera
cam_flip_h = 0
cam_flip_v = 0
# SSDV image resolution
cam_ssdv_res = 128
# video clip duration in minutes
cam_video_dur = 15
# photo snapshot interval in seconds
cam_snapshot_interval = 30