I2C and PE1RXF telemetry added

This commit is contained in:
2023-12-19 19:27:13 +01:00
parent 6daa6610de
commit 4ea12ae960
376 changed files with 46108 additions and 36425 deletions

View File

@@ -7,8 +7,10 @@ cmake_minimum_required(VERSION 3.12)
add_library(LoRa_pico_lib LoRa-RP2040.cpp LoRa-RP2040.h)
add_library(LoRa_print Print.h Print.cpp)
add_library(KISS kiss.h kiss.cpp)
add_library(i2c_sensor i2c_sensor.h i2c_sensor.cpp)
target_link_libraries(LoRa_pico_lib pico_stdlib hardware_spi hardware_interp LoRa_print)
target_link_libraries(i2c_sensor pico_stdlib hardware_i2c)
# enable usb output, disable uart output
pico_enable_stdio_usb(LoRa_pico_lib 1)
@@ -25,7 +27,7 @@ target_include_directories(main PUBLIC ./)
target_link_directories(main PUBLIC ./)
target_link_libraries(main pico_stdlib LoRa_pico_lib LoRa_print KISS)
target_link_libraries(main pico_stdlib LoRa_pico_lib LoRa_print KISS i2c_sensor)
# enable usb output, disable uart output
pico_enable_stdio_usb(main 1)

View File

@@ -1,3 +1,26 @@
/*********************************************************************************
*
* lora_aprs_node_pico is a LoRa APRS KISS modem with additional PE1RXF telemetry
* capabilities. It runs on a Raspberry Pi Pico.
*
* (C)2023 M.T. Konstapel https://meezenest.nl/mees
*
* This file is part of lora_aprs_node_pico.
*
* lora_aprs_node_pico is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lora_aprs_node_pico is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with lora_aprs_node_pico. If not, see <https://www.gnu.org/licenses/>.
*
**********************************************************************************/
#ifndef CONFIG_H
#define CONFIG_H
@@ -57,13 +80,13 @@
// Struct can not be bigger than 4kbyte
struct aprssettings {
uint8_t ValidFlashData = 0x5A; // Indicates flash contains valid data - 1 bytes
uint8_t MyCall[10] = { 'P','E','1','R','X','F','-','5', 0, 0} ; // 10 bytes
uint8_t MyCall[10] = { 'P','E','1','R','X','F','-','6', 0, 0} ; // 10 bytes
uint8_t ServerCall[10] = { 'P','E','1','R','X','F','-','3', 0, 0} ; // 10 bytes
uint8_t Destination[10] = { 'A','P','Z','M','D','M', 0, 0, 0 ,0} ; // 10 bytes
uint8_t Path1[10] = { 0,'I','D','E','1','-', '1', 0, 0, 0} ; // 10 bytes
uint8_t Path2[10] = { 0,'I','D','E','2','-', '2', 0, 0 ,0} ; // 10 bytes
uint8_t FirmwareVersion[20] = { 'V','1',',','C','o','n','t','r', 'o','l','l','e','r',' ','0','1', 0, 0, 0, 0} ;
uint8_t FirmwareVersion[20] = { 'V','2',',','C','o','n','t','r', 'o','l','l','e','r',' ','0','1', 0, 0, 0, 0} ;
// 20 bytes
// Default LoRa settings
@@ -74,10 +97,21 @@
uint16_t loraPaSelect = 1; // 2 bytes
uint32_t loraBandwidth = 125E3; // 4 bytes
uint32_t loraFrequency = 433775000; // 4 bytes
// Telemetry settings
/* Time between telemetry transmissions
* 10 min = 6e+8 us
* 20 min = 12e+8 us
* 30 min = 18e+8 us
* 40 min = 24e+8 us
* 50 min = 30e+8 us
* 60 min = 36e+8 us
*/
uint64_t TelemetryPeriod = 0xFFFFFFFFFFFFFFFF; // 8 bytes, default all ones means telemetry disabled
// Total 89 bytes
// Total 97 bytes
uint8_t FillerData[163];
uint8_t FillerData[146];// was 155
} AprsSettings;
struct status {
@@ -89,6 +123,12 @@
uint8_t StatusString[6] = { '0','0','0','0','0',0};
uint8_t DescriptionString[20] ={ 'N','C',',','C','n','t','r',',','5','V',',','1','2','V',',','2','4','V',0,0};
// Payload for APRS mesage can be up to 67 bytes long. Plus one for the NULL terminator used by C.
uint8_t TelemetryString[68];
uint8_t TelemetryDescriptionString[9] = { 'T','e','m','p',',','H','u','m',0};
uint8_t TelemetryUnitString[8] = { 'd','e','g',' ','C',',','%',0};
uint8_t KissMode = OFF;
} Status;

View File

@@ -1,3 +1,26 @@
/*********************************************************************************
*
* lora_aprs_node_pico is a LoRa APRS KISS modem with additional PE1RXF telemetry
* capabilities. It runs on a Raspberry Pi Pico.
*
* (C)2023 M.T. Konstapel https://meezenest.nl/mees
*
* This file is part of lora_aprs_node_pico.
*
* lora_aprs_node_pico is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lora_aprs_node_pico is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with lora_aprs_node_pico. If not, see <https://www.gnu.org/licenses/>.
*
**********************************************************************************/
#include "LoRa-RP2040.h"
// registers

View File

@@ -1,3 +1,26 @@
/*********************************************************************************
*
* lora_aprs_node_pico is a LoRa APRS KISS modem with additional PE1RXF telemetry
* capabilities. It runs on a Raspberry Pi Pico.
*
* (C)2023 M.T. Konstapel https://meezenest.nl/mees
*
* This file is part of lora_aprs_node_pico.
*
* lora_aprs_node_pico is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lora_aprs_node_pico is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with lora_aprs_node_pico. If not, see <https://www.gnu.org/licenses/>.
*
**********************************************************************************/
#ifndef LORA_H
#define LORA_H

151
src/i2c_sensor.cpp Normal file
View File

@@ -0,0 +1,151 @@
/*********************************************************************************
*
* lora_aprs_node_pico is a LoRa APRS KISS modem with additional PE1RXF telemetry
* capabilities. It runs on a Raspberry Pi Pico.
*
* (C)2023 M.T. Konstapel https://meezenest.nl/mees
*
* This file is part of lora_aprs_node_pico.
*
* lora_aprs_node_pico is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lora_aprs_node_pico is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with lora_aprs_node_pico. If not, see <https://www.gnu.org/licenses/>.
*
**********************************************************************************/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "i2c_sensor.h"
/*******************************************************************************
* Function Definitions
*/
// Write 1 byte to the specified register
int reg_write( i2c_inst_t *i2c,
const uint addr,
const uint8_t reg,
uint8_t *buf,
const uint8_t nbytes) {
int num_bytes_read = 0;
uint8_t msg[nbytes + 1];
// Check to make sure caller is sending 1 or more bytes
if (nbytes < 1) {
return 0;
}
// Append register address to front of data packet
msg[0] = reg;
for (int i = 0; i < nbytes; i++) {
msg[i + 1] = buf[i];
}
// Write data to register(s) over I2C
i2c_write_timeout_us(i2c, addr, msg, (nbytes + 1), false, 1000000);
return num_bytes_read;
}
// Read byte(s) from specified register. If nbytes > 1, read from consecutive
// registers.
int reg_read( i2c_inst_t *i2c,
const uint addr,
const uint8_t reg,
uint8_t *buf,
const uint8_t nbytes) {
int num_bytes_read = 0;
// Check to make sure caller is asking for 1 or more bytes
if (nbytes < 1) {
return 0;
}
// Read data from register(s) over I2C
i2c_write_timeout_us(i2c, addr, &reg, 1, true, 1000000);
num_bytes_read = i2c_read_timeout_us(i2c, addr, buf, nbytes, false, 1000000);
return num_bytes_read;
}
/*******************************************************************************
* Initialize
*/
int initAM2315(void) {
int16_t humidity;
int16_t temperature;
// Ports
i2c_inst_t *i2c = i2c1;
// Buffer to store raw reads
uint8_t data[6];
//Initialize I2C port at 100 kHz
i2c_init(i2c, 100 * 1000);
// Initialize I2C pins
gpio_set_function(PIN_SDA, GPIO_FUNC_I2C);
gpio_set_function(PIN_SCL, GPIO_FUNC_I2C);
gpio_pull_up(PIN_SDA);
gpio_pull_up(PIN_SCL);
// Wake up AM2315
reg_write(i2c, AM2315_I2CADDR, AM2315_READREG, data, 1);
sleep_ms(10);
// Request read registers from AM2315
data[0]=0x00;// start at address 0x0
data[1]=4;// request 4 bytes data
reg_write(i2c, AM2315_I2CADDR, AM2315_READREG, data, 3);
// Actual read registers
reg_read(i2c, AM2315_I2CADDR, AM2315_READREG, data, 8);
if (data[0] != AM2315_READREG) {
return 1;
}
return 0;
}
int ReadAM2315(int16_t* humidity, int16_t* temperature){
// Ports
i2c_inst_t *i2c = i2c1;
// Buffer to store raw reads
uint8_t data[6];
// Wake up AM2315
reg_write(i2c, AM2315_I2CADDR, AM2315_READREG, data, 1);
sleep_ms(10);
// Request read registers from AM2315
data[0]=0x00;// start at address 0x0
data[1]=4;// request 4 bytes data
reg_write(i2c, AM2315_I2CADDR, AM2315_READREG, data, 3);
// Actual read registers
reg_read(i2c, AM2315_I2CADDR, AM2315_READREG, data, 8);
// Convert 2 bytes (little-endian) into 16-bit integer (signed)
*humidity = (int16_t)((data[2] << 8) | data[3]);
*temperature = (int16_t)((data[4] << 8) | data[5]);
}

48
src/i2c_sensor.h Normal file
View File

@@ -0,0 +1,48 @@
/*********************************************************************************
*
* lora_aprs_node_pico is a LoRa APRS KISS modem with additional PE1RXF telemetry
* capabilities. It runs on a Raspberry Pi Pico.
*
* (C)2023 M.T. Konstapel https://meezenest.nl/mees
*
* This file is part of lora_aprs_node_pico.
*
* lora_aprs_node_pico is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lora_aprs_node_pico is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with lora_aprs_node_pico. If not, see <https://www.gnu.org/licenses/>.
*
**********************************************************************************/
#include "hardware/i2c.h"
#define AM2315_I2CADDR 0x5C // or is it 0x5C 0xB8
#define AM2315_READREG 0x03
#define PIN_SDA 26
#define PIN_SCL 27
/*******************************************************************************
* Function Declarations
*/
int reg_write(i2c_inst_t *i2c,
const uint addr,
const uint8_t reg,
uint8_t *buf,
const uint8_t nbytes);
int reg_read( i2c_inst_t *i2c,
const uint addr,
const uint8_t reg,
uint8_t *buf,
const uint8_t nbytes);
int initAM2315(void);
int ReadAM2315(int16_t* humidity, int16_t* temperature);

View File

@@ -1,3 +1,26 @@
/*********************************************************************************
*
* lora_aprs_node_pico is a LoRa APRS KISS modem with additional PE1RXF telemetry
* capabilities. It runs on a Raspberry Pi Pico.
*
* (C)2023 M.T. Konstapel https://meezenest.nl/mees
*
* This file is part of lora_aprs_node_pico.
*
* lora_aprs_node_pico is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lora_aprs_node_pico is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with lora_aprs_node_pico. If not, see <https://www.gnu.org/licenses/>.
*
**********************************************************************************/
#include "kiss.h"
/*

View File

@@ -1,3 +1,26 @@
/*********************************************************************************
*
* lora_aprs_node_pico is a LoRa APRS KISS modem with additional PE1RXF telemetry
* capabilities. It runs on a Raspberry Pi Pico.
*
* (C)2023 M.T. Konstapel https://meezenest.nl/mees
*
* This file is part of lora_aprs_node_pico.
*
* lora_aprs_node_pico is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lora_aprs_node_pico is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with lora_aprs_node_pico. If not, see <https://www.gnu.org/licenses/>.
*
**********************************************************************************/
#ifndef KISS_H
#define KISS_H
#include <stdio.h>

View File

@@ -1,3 +1,8 @@
/*
* This file was used to port the LoRa software from the Arduino to the Raspberry Pi Pico SDK.
* It is included for archival purposes. It is not part of the lora_aprs_node_pico software.
*/
#include <SPI.h>
#include "LoRa.h"
#include "Config.h"

View File

@@ -1,3 +1,26 @@
/*********************************************************************************
*
* lora_aprs_node_pico is a LoRa APRS KISS modem with additional PE1RXF telemetry
* capabilities. It runs on a Raspberry Pi Pico.
*
* (C)2023 M.T. Konstapel https://meezenest.nl/mees
*
* This file is part of lora_aprs_node_pico.
*
* lora_aprs_node_pico is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lora_aprs_node_pico is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with lora_aprs_node_pico. If not, see <https://www.gnu.org/licenses/>.
*
**********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <time.h>
@@ -9,12 +32,15 @@
#include "Config.h"
#include "kiss.h"
#include "hardware/claim.h"
#include "i2c_sensor.h"
KissClass Kiss;
struct ax25_frame AX25Frame; //defined in kiss.h
struct aprs_frame AprsFrame; //defined in kiss.h
struct kiss_tx_frame KissTxFrame; //defined in kiss.h
bool NO_I2C_AVAILABLE=false;
bool startRadio();
void getPacketData(int packetLength);
int compare_strings(uint8_t a[], uint8_t b[]);
@@ -87,7 +113,9 @@ uint8_t SaveSettingsToFlash(void)
void ShowSettings(void)
{
log_out("LoRa APRS remote switcher with build in KISS TNC.\n");
uint64_t tmp;
log_out("LoRa APRS KISS TNC with support for PE1RXF telemetry.\n");
log_out(" Firmware version : %s\n",AprsSettings.FirmwareVersion);
log_out(" Size of struct : %u.\n\n", sizeof(AprsSettings));
@@ -105,7 +133,15 @@ void ShowSettings(void)
log_out(" CodingRate : %i\n", AprsSettings.loraCodingRate);
log_out(" TxPower : %i\n", AprsSettings.loraTxPower);
log_out(" PaSelect : %i\n", AprsSettings.loraPaSelect);
log_out(" Bandwidth : %u\n", AprsSettings.loraBandwidth);
log_out(" Bandwidth : %u\n\n", AprsSettings.loraBandwidth);
log_out("Telemetry settings\n");
if (AprsSettings.TelemetryPeriod == 0xFFFFFFFFFFFFFFFF)
tmp=0;
else
tmp = AprsSettings.TelemetryPeriod/60000000;
log_out(" Period : %u\n", (uint32_t)tmp);
}
uint8_t ReadSettingsFromFlash(void)
@@ -133,6 +169,8 @@ void setup(void)
// Buffers
memset(rxBuffer, 0, sizeof(rxBuffer));
memset(txBuffer, 0, sizeof(txBuffer));
Status.TelemetryString[0] = '0';
Status.TelemetryString[1] = 0;
gpio_init(PowerSupply24VControl);
gpio_init(PowerSupply12VControl);
@@ -158,9 +196,21 @@ void setup(void)
gpio_put(RelayOffControl, 0);
gpio_put(RelayOnControl, 0);
Status.ControlRelay = OFF;
// Without a delay, the serial port does not work...
sleep_ms(5000);
log_out("Trying to connect to AM2315 I2C sensor...");
// Initialize I2C
if (initAM2315()) {
NO_I2C_AVAILABLE = true;
log_out("not found.\n");
log_out("Trying to continue without I2C\n");
} else {
NO_I2C_AVAILABLE = false;
log_out("connected.\n");
}
ReadSettingsFromFlash();
startRadio();
@@ -180,6 +230,8 @@ void print_help(void)
log_out(" APRS settings.\n");
log_out("freq/spread/pre/rate/power/pa/band.\n");
log_out(" LoRa settings.\n");
log_out("period.\n");
log_out(" Telemetry settings.\n\n");
}
@@ -415,6 +467,20 @@ void ProcessSerialInput(char string[])
log_out("LoRa PA set to %u.\n", AprsSettings.loraPaSelect);
}
}
// Set telemetry interval (can be between 0 and 6)
else if (strcmp(command, "period") == 0) {
tmp = ConvertStringToValue(parameter);
if (tmp == 0xFFFFFFFF || tmp > 6)
log_out("ERROR: that is not a valid value.\n");
else {
if (tmp==0) {
AprsSettings.TelemetryPeriod = 0xFFFFFFFFFFFFFFFF;
} else {
AprsSettings.TelemetryPeriod = tmp * 6e+8;
}
log_out("Telemtry period set to %u minutes.\n", tmp*10);
}
}
// Restart radio
else if (strcmp(command, "restart") == 0)
if (strcmp(parameter, "lora") == 0) {
@@ -510,9 +576,18 @@ void ReadUSBSerial(void)
int main() {
uint16_t ServerCommand = 0;
uint16_t TxDelay = 0;
uint16_t ServerCommand = 0;
uint16_t TxDelay = 0;
uint64_t TelemetryDelay = 0;
uint16_t TelemetryManualRequest = 0;
int16_t humidity=0;
int16_t temperature=0;
char tmp_string[68];
uint16_t cnt;
setup();
while (1) {
@@ -544,6 +619,19 @@ int main() {
case 1 :
ComposeAprsFrame(AprsSettings.FirmwareVersion);
break;
// Send telemetry data
case 3:
// Force a telemtry transmission
TelemetryManualRequest = 1;
break;
// Send telemetry data description fields
case 4:
ComposeAprsFrame(Status.TelemetryDescriptionString);
break;
case 5:
ComposeAprsFrame(Status.TelemetryUnitString);
break;
// Send status of output pins
case 6 :
if (Status.PowerSupply24V == ON)
@@ -573,7 +661,38 @@ int main() {
// Send description digital outputs
case 7 :
ComposeAprsFrame(Status.DescriptionString);
break;
// Time between telemetry transmissions in microseconds. Data is volatile! eg. not stored in FLASH, default after power on is 10 minutes
// Interval telemetry data: never send data
case 20:
AprsSettings.TelemetryPeriod = 0xFFFFFFFFFFFFFFFF;
break;
// Interval telemetry data: 10 minutes
case 21:
AprsSettings.TelemetryPeriod = 6e+8;
break;
// Interval telemetry data: 20 minutes
case 22:
AprsSettings.TelemetryPeriod = 12e+8;
break;
// Interval telemetry data: 30 minutes
case 23:
AprsSettings.TelemetryPeriod = 18e+8;
break;
// Interval telemetry data: 40 minutes
case 24:
AprsSettings.TelemetryPeriod = 24e+8;
break;
// Interval telemetry data: 50 minutes
case 25:
AprsSettings.TelemetryPeriod = 30e+8;
break;
// Interval telemetry data: 60 minutes
case 26:
AprsSettings.TelemetryPeriod = 36e+8;
break;
// Switch off 24V power supply
case 30 :
gpio_put(PowerSupply24VControl, 0);
@@ -625,7 +744,36 @@ int main() {
ServerCommand = 0;
}
/* Periodically send telemetry data */
if ( (time_us_64() - TelemetryDelay > AprsSettings.TelemetryPeriod) || TelemetryManualRequest ){
// Reset appropriate flag
if (TelemetryManualRequest)
TelemetryManualRequest = 0;
else
TelemetryDelay = time_us_64();
// Read humidity and temperature
if (!NO_I2C_AVAILABLE)
ReadAM2315(&humidity, &temperature);
// Format telemetry string
sprintf(tmp_string, "%.1f,%.1f", (float)temperature/10, (float)humidity/10);
// Copy string (including NULL terminator) to final destination (can not be done without temporary string due to char/uint8_t issues)
cnt=0;
while ( cnt <= strlen(tmp_string) ) {
Status.TelemetryString[cnt]=tmp_string[cnt];
cnt++;
}
// Print results
log_out("Sending telemetry: Temp: %.1f, Hum: %.1f\r\n", (float)temperature/10, (float)humidity/10);
ComposeAprsFrame(Status.TelemetryString);
}
/* A message is ready to be send */
if (TransmitRequest) {
@@ -639,10 +787,10 @@ int main() {
transmit();
TransmitRequest = false;
}
}
// Read serial input and process it
ReadUSBSerial();
}
// Read serial input and process it
ReadUSBSerial();
}
return 0;