mirror of
https://codeberg.org/mclemens/hl2-interface.git
synced 2024-11-08 05:12:06 -05:00
fixed problem with negative dBm values
This commit is contained in:
parent
8011993093
commit
5dd4dea308
@ -1,389 +1,412 @@
|
|||||||
//***************************************************************************************
|
/****************************************************************************************************************************
|
||||||
//* PA70 Controller - Band, and Fan Control by Temperature for Arduino Nano *
|
Remote PA Monitor - solution to remotely monitor RF power, SWR and more of QO-100 power amplifiers
|
||||||
//* To be used together with Hermes Lite v2 (http://www.hermeslite.com/) *
|
|
||||||
//* by Cesc Gudayol (EA3IGT) *
|
|
||||||
//* Version 3.0.1 01/04/2021 *
|
|
||||||
//* *
|
|
||||||
//* More info at: https://github.com/ea3igt/HL2-PA70 *
|
|
||||||
//* *
|
|
||||||
//***************************************************************************************
|
|
||||||
//* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND *
|
|
||||||
//***************************************************************************************
|
|
||||||
//* v2.0 * 24/10/2020 * Initial version *
|
|
||||||
//* v2.1 * 27/10/2020 * Convert sendOled to a function to refresh the OLED display *
|
|
||||||
//* V2.2 * 25/11/2020 * Store last band selected in EPROM *
|
|
||||||
//* * 12/12/2020 * Get 6 least significative I2C bus bits to select the band *
|
|
||||||
//* V2.3 * 14/12/2020 * Use EXTTR to control PTT status *
|
|
||||||
//* V3.0 * 20/02/2021 * First version to test new Control Board v2.1 *
|
|
||||||
//* V3.0.1 * 01/04/2021 * Correct OLED refresh problems *
|
|
||||||
//***************************************************************************************
|
|
||||||
//
|
|
||||||
// Pin Configuration:
|
|
||||||
// - PIN A00 OUTPUT: SCL for I2C Master (OLED display)
|
|
||||||
// - PIN A01 OUTPUT: SDA for I2C Master (OLED display)
|
|
||||||
// - PIN A04 INPUT: SDA for I2C Slave (Hermes Lite 2 Control bus)
|
|
||||||
// - PIN A05 INPUT: SCL for I2C Slave (Hermes Lite 2 Control bus)
|
|
||||||
// - PIN A03 INPUT: NTC divider voltage
|
|
||||||
// - PIN D02 INPUT: EXTTR (PTT) control from Hermes Lite 2
|
|
||||||
// - PIN D03 OUTPUT: LPF Band 1 Control (80m)
|
|
||||||
// - PIN D04 OUTPUT: LPF Band 2 Control (40/60m)
|
|
||||||
// - PIN D05 OUTPUT: LPF Band 3 Control (30/20m)
|
|
||||||
// - PIN D06 OUTPUT: LPF Band 4 Control (17/15/12/10m)
|
|
||||||
// - PIN D07 LPF Spare
|
|
||||||
// - PIN D08 LPF Spare
|
|
||||||
// - PIN D09 LPF Spare
|
|
||||||
// - PIN D10 LPF Spare -> Antenna Switch
|
|
||||||
// - PIN D11 OUTPUT: PWM for Fan control f(Temp)
|
|
||||||
// - PIN D12 OUTPUT: PTT Control to the Power Amp
|
|
||||||
|
|
||||||
#include <Wire.h> //For I2C control
|
For Ethernet shields using WT32_ETH01 (ESP32 + LAN8720)
|
||||||
#include <U8g2lib.h> //For SSD1306 Chip Control (OLED)
|
Uses WebServer_WT32_ETH01, a library for the Ethernet LAN8720 in WT32_ETH01 to run WebServer
|
||||||
#include <EEPROM.h> //To store values from PA70-Controller
|
|
||||||
#include <util/delay.h> //Library to delay inside one Interrupt
|
|
||||||
|
|
||||||
//#define TEST //Uncomment if Testing (Serial Monitor traces)
|
Michael Clemens, DK1MI
|
||||||
|
Licensed under MIT license
|
||||||
|
|
||||||
// Declaration for an SH1106 display connected to I2C
|
*****************************************************************************************************************************/
|
||||||
// U8G2_RX: Rotation (R0 = 0º | R1 = 90º | R2 = 180º | R3 = 270º | MIRROR)
|
|
||||||
// SW SCL pin A0
|
|
||||||
// SW SDA pin A1
|
|
||||||
// Use U8X8_PIN_NONE if the reset pin is not connected (All Boards without Reset of the Display)
|
|
||||||
U8G2_SH1106_128X64_NONAME_2_SW_I2C u8g2(U8G2_R0, A0, A1, U8X8_PIN_NONE);
|
|
||||||
|
|
||||||
// Declaration for the Hermes Lites v2 I2C (Listen to Adress 0x20)
|
#define DEBUG_ETHERNET_WEBSERVER_PORT Serial
|
||||||
// HW SDA pin A4
|
|
||||||
// HW SCL pin A5
|
|
||||||
|
|
||||||
// Thermometer definitions
|
// Debug Level from 0 to 4
|
||||||
int ThermistorPin = 3; //Pin A3 for NTC voltage divider reading
|
#define _ETHERNET_WEBSERVER_LOGLEVEL_ 3
|
||||||
int Vo; //To store thermistor bridge readings
|
|
||||||
float R1 = 10000; //Adjust to the R value for the divider (About 10K Ohm)
|
|
||||||
float logR2, R2, T;
|
|
||||||
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;
|
|
||||||
|
|
||||||
// PWM definitions
|
#include <WebServer_WT32_ETH01.h>
|
||||||
const byte PWM_Pin = 11; //PWM Pin
|
#include "index.h" // Main Web page header file
|
||||||
|
#include "config.h" // Config Web page header file
|
||||||
|
#include <Preferences.h>
|
||||||
|
|
||||||
// LPF Output Pins (D3..D10 pins can be used)
|
Preferences translation_fwd;
|
||||||
#define LPF_band1 3 //Pin D3
|
Preferences translation_ref;
|
||||||
#define LPF_band2 4 //Pin D4
|
Preferences config;
|
||||||
#define LPF_band3 5 //Pin D5
|
|
||||||
#define LPF_band4 6 //Pin D6
|
|
||||||
|
|
||||||
#define Antenna 19 //Pin D10
|
String config_items [ ] = {"show_fwd", "show_ref", "show_swr", "show_mV", "show_dBm", "show_watt"};
|
||||||
|
String config_defaults [ ] = {"true", "true", "true", "true", "false", "true"};
|
||||||
|
|
||||||
// PTT Control
|
int voltage_fwd,voltage_ref;
|
||||||
#define EXTTR 2 //Pin D2
|
float fwd_dbm=0, ref_dbm=0;
|
||||||
#define PTTpin 12 //Pin D12
|
double fwd_watt=0, ref_watt=0;
|
||||||
|
byte iii=0;
|
||||||
|
|
||||||
// Other Configurations
|
String conf_content;
|
||||||
float initialTempFanActivation = 27; //Minimum temperature for Fan Activation
|
String conf_translate_fwd_table = "";
|
||||||
float tempFanActivation; //to implement the histeresis cycle
|
String conf_translate_ref_table = "";
|
||||||
float previousTemp_fanActivation; //to implement the histeresis cycle
|
String conf_config_table = "";
|
||||||
bool fanConnected = false; //to store if Fan is activated to show on OLED
|
String del_action = "";
|
||||||
String myBand="---"; //to store myBand String
|
|
||||||
float myTemp; //to store Temperature read from NTC
|
|
||||||
byte selectedBand; //to store Selected Band
|
|
||||||
byte previousSelectedBand; //to store previously Selected Band
|
|
||||||
byte previousI2CBand; //to store previously I2C Band decoded
|
|
||||||
byte PTTStatus = 0; //to store global PTT Status
|
|
||||||
bool PTTChanged = false; //to store global PTT Status Changed
|
|
||||||
int selected_antenna = 0;
|
|
||||||
|
|
||||||
// SetUp function initializations
|
String band = "70cm";
|
||||||
void setup() {
|
String band_fwd = band + "_fwd";
|
||||||
#ifdef TEST
|
String band_ref = band + "_ref";
|
||||||
Serial.begin(9600);
|
String band_list []= {"3cm", "13cm", "70cm", "2m"};
|
||||||
#endif
|
|
||||||
|
|
||||||
// U8G2 Display initialization
|
int IO2_FWD = 2;
|
||||||
u8g2.begin();
|
int IO4_REF = 4;
|
||||||
u8g2.setFont(u8g2_font_helvB12_tr);
|
|
||||||
u8g2.firstPage();
|
|
||||||
do {
|
|
||||||
u8g2.drawStr(5,25,"PA70 Ctrl v3.0.1"); //Software version
|
|
||||||
u8g2.drawStr(5,53," EA3IGT"); //Change to whatever you want
|
|
||||||
} while ( u8g2.nextPage() );
|
|
||||||
|
|
||||||
// I2C Slave Setup
|
WebServer server(80);
|
||||||
Wire.begin(0x20); // join i2c bus with address to listen
|
|
||||||
Wire.onReceive(receiveEvent); // register event
|
|
||||||
|
|
||||||
// Fan Setup
|
// Select the IP address according to your local network
|
||||||
tempFanActivation = initialTempFanActivation;
|
//IPAddress myIP(192, 168, 88, 247);
|
||||||
previousTemp_fanActivation = tempFanActivation;
|
//IPAddress myGW(192, 168, 88, 1);
|
||||||
|
//IPAddress mySN(255, 255, 255, 0);
|
||||||
|
|
||||||
// LPF Setup
|
// Google DNS Server IP
|
||||||
pinMode(LPF_band1, OUTPUT);
|
//IPAddress myDNS(8, 8, 8, 8);
|
||||||
pinMode(LPF_band2, OUTPUT);
|
|
||||||
pinMode(LPF_band3, OUTPUT);
|
|
||||||
pinMode(LPF_band4, OUTPUT);
|
|
||||||
|
|
||||||
// Antenna
|
|
||||||
pinMode(Antenna, OUTPUT);
|
|
||||||
|
|
||||||
// OLED Setup
|
// converts dBm to Watt
|
||||||
pinMode(A0,OUTPUT);
|
double dbm_to_watt(float dbm) {
|
||||||
pinMode(A1,OUTPUT);
|
return pow( 10.0, (dbm - 30.0) / 10.0);
|
||||||
|
}
|
||||||
// PTT Setup
|
|
||||||
pinMode(PTTpin,OUTPUT);
|
// takes a voltage value and translates it
|
||||||
pinMode(EXTTR,INPUT);
|
// to dBm based on the corresponding lookup table
|
||||||
|
float millivolt_to_dbm(int mv, bool fwd)
|
||||||
// PWM Setup
|
{
|
||||||
pinMode(PWM_Pin,OUTPUT);
|
float lastval = 0;
|
||||||
|
float nextval = 0;
|
||||||
delay(200);
|
int lastkey = 0;
|
||||||
|
int nextkey = 0;
|
||||||
//Listen to EXTTR status change
|
float stored_val =0;
|
||||||
attachInterrupt(digitalPinToInterrupt(EXTTR),changePTT,CHANGE);
|
for (int i=0; i<3400; i++) {
|
||||||
|
if (fwd) {
|
||||||
//Get stored Band from EEPROM for initial filter selection
|
stored_val = translation_fwd.getFloat(String(i).c_str());
|
||||||
previousSelectedBand=EEPROM.read(0); //Read LPF filter Band from EEPROM byte 0
|
} else {
|
||||||
previousI2CBand=EEPROM.read(1); //Read I2C byte Band from EEPROM byte 1
|
stored_val = translation_ref.getFloat(String(i).c_str());
|
||||||
|
}
|
||||||
#ifdef TEST
|
if (!isnan(stored_val)) {
|
||||||
Serial.print(F("*** Previous I2C Band: "));
|
if (i < mv) {
|
||||||
Serial.println(previousI2CBand);
|
lastval = stored_val;
|
||||||
Serial.print(F("*** Previous Selected Band: "));
|
lastkey = i;
|
||||||
Serial.println(previousSelectedBand);
|
} else {
|
||||||
Serial.println(F("Initializing..."));
|
nextval = stored_val;
|
||||||
Serial.println();
|
nextkey = i;
|
||||||
#endif
|
break;
|
||||||
|
}
|
||||||
decodeBand(previousI2CBand);
|
}
|
||||||
setLpfBand(previousSelectedBand); //Select LPF filter
|
}
|
||||||
|
|
||||||
delay(2000); //Delay to show the Logo & Version
|
float lowerkey = min(lastkey, nextkey);
|
||||||
sendOled(); //Refresh OLED
|
float lowerval = min(lastval, nextval);
|
||||||
|
/*
|
||||||
|
float higherkey = max(lastkey, nextkey);
|
||||||
|
|
||||||
|
float higherval = max(lastval, nextval);
|
||||||
|
float diffkey = higherkey - lowerkey;
|
||||||
|
float diffval = higherval - lowerval;
|
||||||
|
float x = diffval / diffkey;
|
||||||
|
float y = mv - lowerkey;
|
||||||
|
float z = x * y;
|
||||||
|
|
||||||
|
float result = lowerval + z;
|
||||||
|
*/
|
||||||
|
float diffkey = max(lastkey, nextkey) - min(lastkey, nextkey);
|
||||||
|
float diffval = max(lastval, nextval) - min(lastval, nextval);
|
||||||
|
float result = lowerval + ((diffval / diffkey) * (mv - lowerkey));
|
||||||
|
|
||||||
|
//Serial.print("measured voltage: " + String(mv) + " LastVal: " + String(lastval) + " LastKey: " + String(lastkey) + " Nextval: " + String(nextval) + " NextKey:" + String(nextkey) + "\n");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// read voltages from both input pins
|
||||||
|
// calculates avaerage value of 20 measurements
|
||||||
|
void read_directional_couplers()
|
||||||
|
{
|
||||||
|
int voltage_sum_fwd = 0;
|
||||||
|
int voltage_sum_ref = 0;
|
||||||
|
for(iii=0; iii<20; iii++) // Take 20 samples and save the highest value
|
||||||
|
{ voltage_sum_fwd += analogReadMilliVolts(IO2_FWD);
|
||||||
|
voltage_sum_ref += analogReadMilliVolts(IO4_REF);
|
||||||
|
//Serial.println(String(voltage_fwd));
|
||||||
|
//if(voltage_fwd > voltage_fwd_peak) voltage_fwd_peak = voltage_fwd; // safe the peak of 10 measurements
|
||||||
|
//if(voltage_ref > voltage_ref_peak) voltage_ref_peak = voltage_ref;
|
||||||
|
}
|
||||||
|
//voltage_fwd = voltage_fwd_peak; // use peak voltage for processing
|
||||||
|
//voltage_ref = voltage_ref_peak;
|
||||||
|
|
||||||
|
voltage_fwd = voltage_sum_fwd/20; // use peak voltage for processing
|
||||||
|
voltage_ref = voltage_sum_ref/20;
|
||||||
|
|
||||||
|
fwd_dbm = millivolt_to_dbm(voltage_fwd, true);
|
||||||
|
ref_dbm = millivolt_to_dbm(voltage_ref, false);
|
||||||
|
|
||||||
|
fwd_watt = dbm_to_watt(fwd_dbm);
|
||||||
|
ref_watt = dbm_to_watt(ref_dbm);
|
||||||
|
|
||||||
|
Serial.print(String(fwd_watt) + "\n");
|
||||||
|
|
||||||
|
//voltage_fwd_peak = 0; // set peak voltages back to 0
|
||||||
|
//voltage_ref_peak = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// delivers the dashboard page in "index.h"
|
||||||
|
void handleRoot()
|
||||||
|
{
|
||||||
|
String s = MAIN_page;
|
||||||
|
server.send(200, "text/html", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// delivers a 404 page if a non-existant resouurce is requested
|
||||||
|
void handleNotFound()
|
||||||
|
{
|
||||||
|
String message = F("File Not Found\n\n");
|
||||||
|
|
||||||
|
message += F("URI: ");
|
||||||
|
message += server.uri();
|
||||||
|
message += F("\nMethod: ");
|
||||||
|
message += (server.method() == HTTP_GET) ? F("GET") : F("POST");
|
||||||
|
message += F("\nArguments: ");
|
||||||
|
message += server.args();
|
||||||
|
message += F("\n");
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < server.args(); i++)
|
||||||
|
{
|
||||||
|
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
server.send(404, F("text/plain"), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// executes the function to gather sensor data
|
||||||
|
// delivers gathered data to dashboard page
|
||||||
|
// invoked periodically by the dashboard page
|
||||||
|
void handleDATA() {
|
||||||
|
read_directional_couplers();
|
||||||
|
|
||||||
|
// calculate SWR
|
||||||
|
float swr = (1 + sqrt(ref_watt/fwd_watt)) / (1 - sqrt(ref_watt/fwd_watt));
|
||||||
|
|
||||||
|
String output = String(fwd_watt,3) + ";" + String(fwd_dbm,3) + ";" + String(voltage_fwd) + ";" + String(ref_watt,3) + ";" + String(ref_dbm,3) + ";" + String(voltage_ref) + ";" + String(swr) + ";" + band;
|
||||||
|
server.send(200, "text/plane", output);
|
||||||
|
}
|
||||||
|
|
||||||
|
// main function for displaying the configuration page
|
||||||
|
// invoked by the "configuration" button on the dashboard page
|
||||||
|
void handleCONFIG() {
|
||||||
|
if (conf_translate_fwd_table == "") {
|
||||||
|
build_translate_table(true);
|
||||||
|
}
|
||||||
|
if (conf_translate_ref_table == "") {
|
||||||
|
build_translate_table(false);
|
||||||
|
}
|
||||||
|
if (conf_config_table == "") {
|
||||||
|
build_config_table();
|
||||||
|
}
|
||||||
|
|
||||||
|
conf_content = "<!DOCTYPE HTML>\r\n<html>";
|
||||||
|
conf_content += "<style>";
|
||||||
|
conf_content += ".styled-table{border-collapse: collapse; margin: 25px 0; font-size: 0.9em; font-family: sans-serif; min-width: 400px; box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);}.styled-table thead tr{background-color: #009879; color: #ffffff; text-align: left;}.styled-table tbody tr{border-bottom: 1px solid #dddddd;}.styled-table tbody tr:nth-of-type(even){background-color: #f3f3f3;}.styled-table tbody tr:last-of-type{border-bottom: 2px solid #009879;}.styled-table tbody tr.active-row{font-weight: bold; color: #009879;}";
|
||||||
|
conf_content += ".button{background-color: #009879; border: none; color: white; padding: 5px 5px; text-align: center; text-decoration: none; display: inline-block; margin: 4px 2px; cursor: pointer; border-radius: 8px;}";
|
||||||
|
conf_content += "</style>";
|
||||||
|
conf_content += "<h1>Configuration</h1>";
|
||||||
|
conf_content += "<h3>Band Selection</h1>";
|
||||||
|
conf_content += "<form method='POST' action='/selectband'>";
|
||||||
|
conf_content += "<label for='bands'></label><select class='button' onchange='this.form.submit()'' id='band' name='bands' size='1'>";
|
||||||
|
for (int i=0; i<sizeof band_list/sizeof band_list[0]; i++) {
|
||||||
|
String selected = "";
|
||||||
|
if (band_list[i] == band) {
|
||||||
|
selected = "selected";
|
||||||
|
}
|
||||||
|
conf_content += "<option value='" + band_list[i] + "' " + selected + " >" + band_list[i] + "</option>";
|
||||||
|
}
|
||||||
|
conf_content += "</select></form>";
|
||||||
|
conf_content += "<p>";
|
||||||
|
conf_content += "<h2>Translation Detector voltage /mV to RF-Power level /dBm</h3>";
|
||||||
|
conf_content += "<h3>FWD</h3>";
|
||||||
|
conf_content += conf_translate_fwd_table;
|
||||||
|
conf_content += "<p>";
|
||||||
|
conf_content += "<h3>REF</h3>";
|
||||||
|
conf_content += conf_translate_ref_table;
|
||||||
|
conf_content += "<p>";
|
||||||
|
conf_content += "<h2>General Configuration Items</h3>";
|
||||||
|
conf_content += "<p>";
|
||||||
|
conf_content += conf_config_table;
|
||||||
|
conf_content += "<p><form method='POST' action='/'><button class='button' value='back' name='back' type='submit'>Back to Dashboard</button></form>";
|
||||||
|
conf_content += "</html>";
|
||||||
|
server.send(200, "text/html", conf_content);
|
||||||
|
}
|
||||||
|
|
||||||
|
// generates the translation table for either the FWD or
|
||||||
|
// REF values
|
||||||
|
void build_translate_table(bool fwd) {
|
||||||
|
String tbl = "";
|
||||||
|
if (fwd) {
|
||||||
|
tbl = "<form action=\"/modttfwd\" method=\"POST\">";
|
||||||
|
} else {
|
||||||
|
tbl = "<form action=\"/modttref\" method=\"POST\">";
|
||||||
|
}
|
||||||
|
tbl += "<table class='styled-table'>";
|
||||||
|
tbl += "<thead><tr><td>millivolt (mV)</td><td>decibel-milliwatts (dBm)</td><td>Watt</td><td>Action</td></tr></thead>";
|
||||||
|
|
||||||
|
for (int i=0; i<3400; i++) {
|
||||||
|
float stored_val = 0;
|
||||||
|
if (fwd) {
|
||||||
|
stored_val = translation_fwd.getFloat(String(i).c_str());
|
||||||
|
} else {
|
||||||
|
stored_val = translation_ref.getFloat(String(i).c_str());
|
||||||
|
}
|
||||||
|
if (!isnan(stored_val)) {
|
||||||
|
tbl += "<tr><td>";
|
||||||
|
tbl += String(i);
|
||||||
|
tbl += "</td><td>";
|
||||||
|
tbl += String(stored_val,3);
|
||||||
|
tbl += "</td><td>";
|
||||||
|
tbl += String(dbm_to_watt(stored_val),3);
|
||||||
|
tbl += "</td><td>";
|
||||||
|
tbl += "<button class='button' value='" + String(i) + "' name='delete' type='submit'>delete</button>";
|
||||||
|
tbl += "</td></tr>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tbl += "<tr><td><input name='volt' length=16></td><td><input name='dBm' length=16></td><td> </td><td><button class='button' type='submit'>add/edit</button></td></tr>";
|
||||||
|
tbl += "</table></form>";
|
||||||
|
if (fwd) {
|
||||||
|
conf_translate_fwd_table = tbl;
|
||||||
|
} else {
|
||||||
|
conf_translate_ref_table = tbl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generates the table with generic configuration items
|
||||||
|
void build_config_table() {
|
||||||
|
conf_config_table = "<form action=\"/modcfg\" method=\"POST\">";
|
||||||
|
conf_config_table += "<table class='styled-table'>";
|
||||||
|
conf_config_table += "<thead><tr><td>Key</td><td>Value</td></td><td>Action</td></tr></thead>";
|
||||||
|
for (int i=0; i<sizeof config_items/sizeof config_items[0]; i++) {
|
||||||
|
String stored_val = config.getString(config_items[i].c_str(), "xxx");
|
||||||
|
if (stored_val == "xxx"){
|
||||||
|
config.putString(config_items[i].c_str(), config_defaults[i]);
|
||||||
|
stored_val = config.getString(config_items[i].c_str(), "");
|
||||||
|
}
|
||||||
|
conf_config_table += "<tr><td>";
|
||||||
|
conf_config_table += config_items[i];
|
||||||
|
conf_config_table += "</td><td>";
|
||||||
|
conf_config_table += String(stored_val);
|
||||||
|
conf_config_table += "</td><td>";
|
||||||
|
conf_config_table += "</td></tr>";
|
||||||
|
}
|
||||||
|
conf_config_table += "<tr><td><input name='conf_key' length=16></td><td><input name='conf_value' length=16></td><td><button class='button' type='submit'>edit</button></td></tr>";
|
||||||
|
conf_config_table += "</table></form>";
|
||||||
|
handleCONFIG();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle request from the config page to change or add values
|
||||||
|
// to the FWD value table for the selected band
|
||||||
|
void handleMODTTFWD() {
|
||||||
|
String volt = server.arg("volt");
|
||||||
|
String dBm = server.arg("dBm");
|
||||||
|
del_action = server.arg("delete");
|
||||||
|
if (del_action != "") {
|
||||||
|
translation_fwd.remove(del_action.c_str());
|
||||||
|
} else if (volt != "" and dBm != "") {
|
||||||
|
translation_fwd.putFloat(volt.c_str(), dBm.toFloat());
|
||||||
|
}
|
||||||
|
build_translate_table(true);
|
||||||
|
handleCONFIG();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle request from the config page to change or add values
|
||||||
|
// to the REF value table for the selected band
|
||||||
|
void handleMODTTREF() {
|
||||||
|
String volt = server.arg("volt");
|
||||||
|
String dBm = server.arg("dBm");
|
||||||
|
del_action = server.arg("delete");
|
||||||
|
if (del_action != "") {
|
||||||
|
translation_ref.remove(del_action.c_str());
|
||||||
|
} else if (volt != "" and dBm != "") {
|
||||||
|
translation_ref.putFloat(volt.c_str(), dBm.toFloat());
|
||||||
|
}
|
||||||
|
build_translate_table(false);
|
||||||
|
handleCONFIG();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle request from the config page to change or add values
|
||||||
|
// to the genral config value table for the selected band
|
||||||
|
void handleMODCFG() {
|
||||||
|
String key = server.arg("conf_key");
|
||||||
|
String value = server.arg("conf_value");
|
||||||
|
for (int i=0; i<sizeof config_items/sizeof config_items[0]; i++) {
|
||||||
|
if (config_items[i] == key) {
|
||||||
|
if (key != "" and value != "") {
|
||||||
|
config.putString(config_items[i].c_str(), value);
|
||||||
|
conf_config_table = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
build_config_table();
|
||||||
|
}
|
||||||
|
|
||||||
|
// changes the band according to the user's selection
|
||||||
|
// regenerates the translation tables and fills them
|
||||||
|
// with the values assigned to the respective band
|
||||||
|
// invoked by selecting a band from the select box of teh config page
|
||||||
|
void handleBAND() {
|
||||||
|
band = server.arg("bands");
|
||||||
|
band_fwd = band + "_fwd";
|
||||||
|
band_ref = band + "_ref";
|
||||||
|
translation_fwd.end();
|
||||||
|
translation_ref.end();
|
||||||
|
translation_fwd.begin(band_fwd.c_str(), false);
|
||||||
|
translation_ref.begin(band_ref.c_str(), false);
|
||||||
|
build_translate_table(true);
|
||||||
|
build_translate_table(false);
|
||||||
|
handleCONFIG();
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialization routine
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
analogReadResolution(12);
|
||||||
|
translation_fwd.begin(band_fwd.c_str(), false);
|
||||||
|
translation_ref.begin(band_ref.c_str(), false);
|
||||||
|
config.begin("config", false);
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
while (!Serial);
|
||||||
|
|
||||||
|
// Using this if Serial debugging is not necessary or not using Serial port
|
||||||
|
//while (!Serial && (millis() < 3000));
|
||||||
|
|
||||||
|
Serial.print("\nStarting AdvancedWebServer on " + String(ARDUINO_BOARD));
|
||||||
|
Serial.println(" with " + String(SHIELD_TYPE));
|
||||||
|
Serial.println(WEBSERVER_WT32_ETH01_VERSION);
|
||||||
|
|
||||||
|
// To be called before ETH.begin()
|
||||||
|
WT32_ETH01_onEvent();
|
||||||
|
|
||||||
|
ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER);
|
||||||
|
// Static IP, leave without this line to get IP via DHCP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//ETH.config(myIP, myGW, mySN, myDNS);
|
||||||
|
|
||||||
|
WT32_ETH01_waitForConnect();
|
||||||
|
|
||||||
|
// activates single web server endpoints
|
||||||
|
server.on(F("/"), handleRoot);
|
||||||
|
server.on("/readDATA", handleDATA);
|
||||||
|
server.on("/config", handleCONFIG);
|
||||||
|
server.on("/modttfwd", handleMODTTFWD);
|
||||||
|
server.on("/modttref", handleMODTTREF);
|
||||||
|
server.on("/modcfg", handleMODCFG);
|
||||||
|
server.on("/selectband", handleBAND);
|
||||||
|
|
||||||
|
|
||||||
|
server.onNotFound(handleNotFound);
|
||||||
|
server.begin();
|
||||||
|
|
||||||
|
Serial.print(F("HTTP EthernetWebServer is @ IP : "));
|
||||||
|
Serial.println(ETH.localIP());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main loop program
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
int PWMDuty;
|
server.handleClient();
|
||||||
int Times = 100; //Average N times to be more stable
|
|
||||||
float Temperature = 0; //All thermometer code from: https://bit.ly/3pOUjVo
|
|
||||||
for(int i = 0; i < Times; i++) {
|
|
||||||
Vo = analogRead(ThermistorPin);
|
|
||||||
R2 = R1 * (1024.0 / (float)Vo - 1.0);
|
|
||||||
logR2 = log(R2);
|
|
||||||
T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));
|
|
||||||
T = T - 273.15 + 1; //+1 is my personal adjustment to be more precise
|
|
||||||
Temperature = Temperature + T;
|
|
||||||
if (PTTChanged)
|
|
||||||
{
|
|
||||||
digitalWrite(PTTpin,PTTStatus); //Toggle PTT
|
|
||||||
PTTChanged=false; //Reset PTTChanged
|
|
||||||
}
|
|
||||||
}
|
|
||||||
myTemp = int(Temperature/Times*10)/(float)10.0; //Rounded to get 1 decimal
|
|
||||||
|
|
||||||
PWMDuty = int((myTemp - tempFanActivation)*20); //Calculate PWMDuty (increase to get more aggresive fan)
|
|
||||||
if (PWMDuty < 0)
|
|
||||||
{
|
|
||||||
PWMDuty = 0;
|
|
||||||
}
|
|
||||||
if (PWMDuty > 254)
|
|
||||||
{
|
|
||||||
PWMDuty = 254;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TEST
|
|
||||||
Serial.print(F("Temperature: "));
|
|
||||||
Serial.print(myTemp,1);
|
|
||||||
Serial.print(F(" - PWMDuty: "));
|
|
||||||
Serial.println(PWMDuty);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
analogWrite(PWM_Pin,PWMDuty); //Select the appropriate PWM f(temperature)
|
|
||||||
|
|
||||||
if (PWMDuty > 0 and not(fanConnected)) //Implement histeresis cycle
|
|
||||||
{
|
|
||||||
tempFanActivation = initialTempFanActivation - 1;
|
|
||||||
}
|
|
||||||
if (PWMDuty == 0 and fanConnected)
|
|
||||||
{
|
|
||||||
tempFanActivation = initialTempFanActivation;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PWMDuty > 0)
|
|
||||||
{
|
|
||||||
fanConnected=true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fanConnected=false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TEST
|
|
||||||
if (fanConnected)
|
|
||||||
{
|
|
||||||
Serial.println(F("Fan Connected"));
|
|
||||||
Serial.print(F("Minimum Temperature Fan Deactivation: "));
|
|
||||||
Serial.println(tempFanActivation,1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Serial.println(F("Fan Disconnected"));
|
|
||||||
Serial.print(F("Minimum Temperature Fan Activation: "));
|
|
||||||
Serial.println(tempFanActivation,1);
|
|
||||||
}
|
|
||||||
Serial.print(F("BAND:"));
|
|
||||||
Serial.println(myBand);
|
|
||||||
Serial.println();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sendOled(); //Refresh OLED
|
|
||||||
}
|
|
||||||
|
|
||||||
//Interrupt function to handle any PTT change at HL2 (EXTTR signal)
|
|
||||||
void changePTT()
|
|
||||||
{
|
|
||||||
int myEXTTR = digitalRead(EXTTR);
|
|
||||||
PTTStatus = not(myEXTTR);
|
|
||||||
PTTChanged = true;
|
|
||||||
|
|
||||||
#ifdef TEST
|
|
||||||
Serial.println(F("*** EXTTR Changed ***"));
|
|
||||||
Serial.print(F("Value="));
|
|
||||||
Serial.println(myEXTTR);
|
|
||||||
Serial.print(F("PTTStatus="));
|
|
||||||
Serial.println(PTTStatus);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void receiveEvent(int howMany) { //Triggered when receive I2C information from HL2
|
|
||||||
byte c[10];
|
|
||||||
int i= 0;
|
|
||||||
while (0 < Wire.available()) { // loop through all but the last
|
|
||||||
c[i] = Wire.read(); // receive byte as a character
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TEST
|
|
||||||
Serial.print(F("I2C BUS DATA:"));
|
|
||||||
Serial.println(c[1]); // write to usb monitor
|
|
||||||
#endif
|
|
||||||
|
|
||||||
byte myC=c[1] & B00111111; //Get 6 least significative bits
|
|
||||||
decodeBand(myC); //Decode Band
|
|
||||||
|
|
||||||
// write to LPF "Binary Bus" (Band Selection)
|
|
||||||
setLpfBand(selectedBand);
|
|
||||||
if ((selectedBand!=previousSelectedBand) and (PTTStatus==1))
|
|
||||||
{
|
|
||||||
#ifdef TEST
|
|
||||||
// write to usb monitor
|
|
||||||
Serial.println(F("*** Change Filter: Delay 50 ms ***"));
|
|
||||||
#endif
|
|
||||||
_delay_ms(50); //Delay 50ms to settle LPF filters (if change) before PTT
|
|
||||||
}
|
|
||||||
previousSelectedBand = selectedBand;
|
|
||||||
|
|
||||||
// Toggle PTT
|
|
||||||
digitalWrite(PTTpin,PTTStatus);
|
|
||||||
|
|
||||||
// toggle Antenna
|
|
||||||
digitalWrite(Antenna,selected_antenna);
|
|
||||||
|
|
||||||
//Store Last Selected Band into EEPROM
|
|
||||||
if (PTTStatus)
|
|
||||||
{
|
|
||||||
EEPROM.write(0,selectedBand); //Byte 0 for selectedBand
|
|
||||||
EEPROM.write(1,myC); //Byte 1 for I2C decoded
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TEST
|
|
||||||
// write to usb monitor
|
|
||||||
Serial.print(F("LPF BAND CONTROL (Binary):"));
|
|
||||||
Serial.println(selectedBand);
|
|
||||||
Serial.print(F("PTT CONTROL:"));
|
|
||||||
Serial.println(PTTStatus);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//Function to activate the appropriate filter band at LPF
|
|
||||||
//***************** Change accordingly ******************
|
|
||||||
void setLpfBand(int lpfBand)
|
|
||||||
{
|
|
||||||
// write to LPF "Binary Bus" (Band Selection)
|
|
||||||
digitalWrite(LPF_band1, lpfBand & B0001);
|
|
||||||
digitalWrite(LPF_band2, lpfBand & B0010);
|
|
||||||
digitalWrite(LPF_band3, lpfBand & B0100);
|
|
||||||
digitalWrite(LPF_band4, lpfBand & B1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Function to decode HL2 band and select/map the filter
|
|
||||||
//**************** Change accordingly *****************
|
|
||||||
void decodeBand(byte c)
|
|
||||||
{
|
|
||||||
switch (c) {
|
|
||||||
case 0x1: //160m
|
|
||||||
selectedBand = B0001;
|
|
||||||
myBand = F("160m");
|
|
||||||
selected_antenna = 0;
|
|
||||||
break;
|
|
||||||
case 0x2: //80m
|
|
||||||
selectedBand = B0001;
|
|
||||||
myBand = F("80m");
|
|
||||||
selected_antenna = 0;
|
|
||||||
break;
|
|
||||||
case 0x4: //60m & 40m
|
|
||||||
selectedBand = B0010;
|
|
||||||
myBand = F("60/40m");
|
|
||||||
selected_antenna = 0;
|
|
||||||
break;
|
|
||||||
case 0x8: //30m & 20m
|
|
||||||
selectedBand = B0100;
|
|
||||||
myBand = F("30/20m");
|
|
||||||
selected_antenna = 1;
|
|
||||||
break;
|
|
||||||
case 0x10: //17m & 15m
|
|
||||||
selectedBand = B1000;
|
|
||||||
myBand = F("17/15m");
|
|
||||||
selected_antenna = 1;
|
|
||||||
break;
|
|
||||||
case 0x20: //12m & 10m
|
|
||||||
selectedBand = B1000;
|
|
||||||
myBand = F("12/10m");
|
|
||||||
selected_antenna = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
selectedBand=selectedBand; //No Change
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Function to send all the information to the OLED
|
|
||||||
void sendOled(void)
|
|
||||||
{
|
|
||||||
// write to OLED
|
|
||||||
//u8g2.clearBuffer();
|
|
||||||
u8g2.firstPage();
|
|
||||||
do {
|
|
||||||
// u8g2.drawFrame(0,0,128,64);
|
|
||||||
u8g2.setFont(u8g2_font_t0_17_tr);
|
|
||||||
u8g2.drawStr(5,17,"BAND:");
|
|
||||||
|
|
||||||
u8g2.drawStr(55,17,myBand.c_str());
|
|
||||||
u8g2.drawStr(5,37,"TEMP:");
|
|
||||||
String myTempStr=String(myTemp,1);
|
|
||||||
u8g2.drawStr(55,37,myTempStr.c_str());
|
|
||||||
if (fanConnected)
|
|
||||||
{
|
|
||||||
//u8g2.drawStr(97,37,"#");
|
|
||||||
u8g2.setFont(u8g2_font_open_iconic_all_2x_t);
|
|
||||||
u8g2.drawStr(96,39,"\xcd");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//u8g2.drawStr(97,36,"_");
|
|
||||||
u8g2.drawStr(97,36,"Antenna:");
|
|
||||||
u8g2.drawStr(55,36,String(selected_antenna).c_str());
|
|
||||||
}
|
|
||||||
//u8g2.setFont(u8g2_font_t0_17_tr);
|
|
||||||
//u8g2.drawStr(5,57,"TRANSMITING"); //Space for future uses
|
|
||||||
delay(2);
|
|
||||||
} while ( u8g2.nextPage() );
|
|
||||||
u8g2.sendBuffer();
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user