first upload of beta version

This commit is contained in:
richonguzman 2023-01-25 00:42:51 -03:00
parent b6758f4a5b
commit 2736551c76
12 changed files with 427 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

10
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

39
include/README Normal file
View File

@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

46
lib/README Normal file
View File

@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

20
platformio.ini Normal file
View File

@ -0,0 +1,20 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
mikalhart/TinyGPSPlus@^1.0.3
jgromes/RadioLib@^5.5.0
paulstoffregen/Time@^1.6.1
mathertel/OneButton@^2.0.3
monitor_speed = 115200

BIN
src/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,218 @@
/*
LORA (1 Watt Module) APRS Tracker
https://github.com/richonguzman/LoRa_1W_APRS_Tracker
written by Ricardo Guzman ( CD2RXU-7 )
based on lots of other Lora APRS Tracker ideas like:
https://github.com/lora-aprs/LoRa_APRS_Tracker
https://github.com/aprs434/lora.tracker
https://github.com/Mane76/lora.tracker
https://github.com/sh123/esp32_loraprs
*/
#include <SPI.h>
#include <TinyGPS++.h>
#include <RadioLib.h>
#include <WiFi.h>
#include <OneButton.h>
#include "user_config.h"
#include "pins.h"
#include "lora_config.h"
#include "beacon_config.h"
#define VERSION "2023.01.24" // BETA!!!
SX1268 radio = new Module(NSS, DIO1, NRST, BUSY);
HardwareSerial neo6m_gps(1);
TinyGPSPlus gps;
OneButton UserButton1 = OneButton(BUTTON1_PIN, true, true);
static bool send_update = true;
void setup_lora_module() {
int state = radio.begin(LoraFreqTx, LoraBandWidth, LoraSpreadingFactor, LoraCodingRate, LoraSyncWord, LoraOutro, LoraPreampbleLenght);
radio.setOutputPower(Lora_Power);
radio.setRfSwitchPins(RXEN, TXEN);
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("LORA (1 Watt) MODULE Ready (Radiolib success!)"));
} else {
Serial.println(F("Lora Module Setup failed, code "));
Serial.println(state);
}
}
void setup_gps_module() {
neo6m_gps.begin(9600, SERIAL_8N1, GPS_TXD, GPS_RXD);
}
static void ForcedBeaconTx() {
Serial.println("Forced Beacon Tx");
send_update = true;
}
void setup() {
Serial.begin(115200);
Serial.println(F("LoRa tracker " __DATE__ " " __TIME__ " / Callsign ------> " SRC_CALLSIGN));
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
setup_lora_module();
setup_gps_module();
UserButton1.attachClick(ForcedBeaconTx);
WiFi.mode(WIFI_OFF);
btStop();
Serial.print("Version = ");
Serial.println(VERSION);
Serial.println("Transmission Start ---->");
}
uint8_t tx_buffer[256];
uint32_t lastTxTime = 0;
char *ax25_base91enc(char *s, uint8_t n, uint32_t v) {
/* Creates a Base-91 representation of the value in v in the string */
/* pointed to by s, n-characters long. String length should be n+1. */
for(s += n, *s = '\0'; n; n--) {
*(--s) = v % 91 + 33;
v /= 91;
}
return(s);
}
void loop() {
UserButton1.tick();
while (neo6m_gps.available() > 0) {
gps.encode(neo6m_gps.read());
}
bool gps_loc_update = gps.location.isUpdated();
bool gps_time_update = gps.time.isUpdated();
//static time_t nextBeaconTimeStamp = -1;
static double currentHeading = 0;
static double previousHeading = 0;
//static unsigned int rate_limit_message_text = 0;
static double lastTxLatitude = 0.0;
static double lastTxLongitude = 0.0;
static double lastTxDistance = 0.0;
static uint32_t txInterval = 60000L;
//static int speed_zero_sent = 0;
if (!send_update && gps_loc_update) {
uint32_t lastTx = millis() - lastTxTime;
currentHeading = gps.course.deg();
lastTxDistance = TinyGPSPlus::distanceBetween(gps.location.lat(), gps.location.lng(), lastTxLatitude, lastTxLongitude);
if (lastTx >= txInterval) {
if (lastTxDistance > MinimumDistanceTx) {
send_update = true;
}
}
if (!send_update) {
double headingDelta = abs(previousHeading - currentHeading);
if (lastTx > MinimumTimeDeltaBeacon * 1000) {
if (headingDelta > TurnDegrees && lastTxDistance > MinimumDistanceTx) {
send_update = true;
}
}
}
}
if (send_update && gps_loc_update) {
float Tlat, Tlon;
float Tspeed=0, Tcourse=0;
Tlat = gps.location.lat();
Tlon = gps.location.lng();
Tcourse = gps.course.deg();
Tspeed = gps.speed.knots();
uint32_t aprs_lat, aprs_lon;
aprs_lat = 900000000 - Tlat * 10000000;
aprs_lat = aprs_lat / 26 - aprs_lat / 2710 + aprs_lat / 15384615;
aprs_lon = 900000000 + Tlon * 10000000 / 2;
aprs_lon = aprs_lon / 26 - aprs_lon / 2710 + aprs_lon / 15384615;
String Ns, Ew, helper;
if(Tlat < 0) { Ns = "S"; } else { Ns = "N"; }
if(Tlat < 0) { Tlat= -Tlat; }
if(Tlon < 0) { Ew = "W"; } else { Ew = "E"; }
if(Tlon < 0) { Tlon= -Tlon; }
String AprsPacketMsg = "!";
AprsPacketMsg += "/";
char helper_base91[] = {"0000\0"};
int i;
ax25_base91enc(helper_base91, 4, aprs_lat);
for (i=0; i<4; i++) {
AprsPacketMsg += helper_base91[i];
}
ax25_base91enc(helper_base91, 4, aprs_lon);
for (i=0; i<4; i++) {
AprsPacketMsg += helper_base91[i];
}
AprsPacketMsg += SYMBOL;
if (SendAltitude) { // Send Altitude or... (APRS calculates Speed also)
int Alt1, Alt2;
int Talt;
Talt = gps.altitude.feet();
if(Talt>0){
double ALT=log(Talt)/log(1.002);
Alt1= int(ALT/91);
Alt2=(int)ALT%91;
}else{
Alt1=0;
Alt2=0;
}
AprsPacketMsg +=char(Alt1+33);
AprsPacketMsg +=char(Alt2+33);
AprsPacketMsg +=char(0x30+33);
} else { // ... just send Course and Speed
ax25_base91enc(helper_base91, 1, (uint32_t) Tcourse/4 );
AprsPacketMsg += helper_base91[0];
ax25_base91enc(helper_base91, 1, (uint32_t) (log1p(Tspeed)/0.07696));
AprsPacketMsg += helper_base91[0];
AprsPacketMsg += "\x47";
}
if (SendComment) {
AprsPacketMsg += APRS_COMMENT;
}
Serial.print(F("GPS coordinates: ")); // Only for Serial Monitor
Serial.print(Tlat, 6);
Serial.print(F(", "));
Serial.println(Tlon, 6);
memset(tx_buffer, 0x00, sizeof tx_buffer);
uint16_t size = 0;
size = snprintf(reinterpret_cast<char *>(tx_buffer), sizeof tx_buffer, "\x3c\xff\x01%s>%s:%s", SRC_CALLSIGN, DST_CALLSIGN, AprsPacketMsg.c_str());
Serial.print(millis()); // Only for Serial Monitor
Serial.print(F(" transmitting: "));
Serial.println(reinterpret_cast<char *>(tx_buffer));
digitalWrite(LED_BUILTIN, HIGH);
radio.transmit(tx_buffer, size);
radio.finishTransmit();
digitalWrite(LED_BUILTIN, LOW);
lastTxLatitude = gps.location.lat();
lastTxLongitude = gps.location.lng();
previousHeading = currentHeading;
lastTxDistance = 0.0;
lastTxTime = millis();
send_update = false;
}
if (gps_time_update) { // updating txInterval between Slow and FastRate or in between
int curr_speed = (int)gps.speed.kmph();
if (curr_speed < SlowSpeed) {
txInterval = SlowRate * 1000;
} else if (curr_speed > FastSpeed) {
txInterval = FastRate * 1000;
} else {
txInterval = min(SlowRate, (FastSpeed * FastRate / curr_speed)) * 1000;
}
}
}

15
src/beacon_config.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef BEACON_CONFIG_H_
#define BEACON_CONFIG_H_
#define SlowRate 120 // Seg
#define SlowSpeed 10 // Km/h (3 Runner , 5 Bike, 10 Car)
#define FastRate 60 // Seg
#define FastSpeed 20 // Km/h (20 Runner y Bike, 70 Car)
#define TurnDegrees 20 // Degrees before Forced Beacon Tx (20 Car , 15 Bike/Runner)
#define MinimumDistanceTx 30 // Mts (20 Runner, 100 Car/Bike)
#define MinimumTimeDeltaBeacon 5 // Seg between Tx
#define SendAltitude true // "true" adds Altitude to the APRS packet/message, "false" add Course+Speed
#define SendComment false // "true" adds comment to the APRS packet/message
#endif

13
src/lora_config.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef LORA_CONFIG_H_
#define LORA_CONFIG_H_
#define LoraFreqTx 433.775
#define LoraBandWidth 125.0
#define LoraSpreadingFactor 12
#define LoraCodingRate 5
#define LoraSyncWord 0x12
#define LoraOutro 5
#define LoraPreampbleLenght 8
#define Lora_Power 20 // Tx Power, 8=100mW, 20=1000mW
#endif

41
src/pins.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef PINS_H_
#define PINS_H_
#define GPS_TXD 16 // Conection Pinout for GPS
#define GPS_RXD 17
/*
GPS NEO-6M v.2----> ESP32
VCC 3.3V
GND GND
TXD 16
RXD 17
*/
#define NSS 5 // Conection Pinout Ebyte E22 400M30S LoRa Module
#define DIO1 12
#define NRST 27
#define BUSY 14
#define RXEN 32
#define TXEN 25
/*
400M30S-------------------> ESP32
1-2-3-4-5-11-12-20-22 GND
6 RXEN 32
7 TXEN 25
8 X (not connected) -
9-10 5V add 100uf (electro) + 100nF (polyester) from 5V to ground near pin 9-10
13 DIO1 12
14 BUSY 14
15 NRST 27
16 MISO 19
17 MOSI 23
18 SCK 18
19 NSS 5
21 ANTENA
*/
#define LED_BUILTIN 2 // Blue Led ESP32 Pin
#define BUTTON1_PIN 15 // Forced Beacon Tx (Switch pin1 to pin 15 , Swith pin2 to 220 ohms resistor to GND)
#endif

9
src/user_config.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef USER_CONFIG_H_
#define USER_CONFIG_H_
#define SRC_CALLSIGN "CD2RXU-7" // Change "NOCALL-10 to your APRS Callsign
#define DST_CALLSIGN "AP" // APRS Destination (could be also "WIDE1-1")
#define SYMBOL "[" // APRS Symbol: "[" Runner, "b" Bike, ">" Auto/Car
#define APRS_COMMENT "Lora Tracker 1W" // if you want to send any comment change the APRS_COMMENT
// and also beacon_config.h > SendComment = true
#endif

11
test/README Normal file
View File

@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html