I decided it would be useful having telemetry on my 9xr, but I disliked the existing hardware mods and decided to try to use the port on the back of the djt module and connect a hd44780 display and an arduino nano. The tricky part was inverting the signal by using SoftwareSerial instead of hardware.
I’m very pleased with the result. Showing A1, A2, RSSI for both rx and tx. On the receiver side I’m using a voltage divider with 10k and 2k2 resistors hooked up to A2.
#include <SoftwareSerial.h> #include <LiquidCrystal.h> #define DE_BUG // Change this to #define DEBUG if needed #define DE_BUG_HEX #define FRS_TX_PIN A2 // not used #define FRS_RX_PIN A3 // telemetry data #define FRAME_SIZE 12 // max 12 bytes #define FRAME_RVLQ 0xFE // second byte 0xFE - Remote Voltage and Link Quality #define FRAME_USER 0xFD // second byte 0xFD - User Data #define DISP_INTERVAL 500 // ms SoftwareSerial FrSky = SoftwareSerial(FRS_TX_PIN, FRS_RX_PIN, true); // orig false LiquidCrystal lcd(2, 3, 4, 5, 6, 7 ); byte next = 0; byte buff[FRAME_SIZE]; // frame array byte index = 0; // index in frame array byte link = 0; // link established, data received byte frame = 0; // frame received indicator byte stuff = 0; // byte stuffing indicator int Rx[DISP_INTERVAL/15]; // Up Link Quality RSSI int Tx[DISP_INTERVAL/15]; // Down Link Quality RSSI int V1[DISP_INTERVAL/15]; // Port 1 voltage, V * 100 int V2[DISP_INTERVAL/15]; // Port 2 voltage, V * 100 unsigned long dispTime = 0; // time when info was updated, ms unsigned long prevTime = 0; // time when 0xFE frame was received, ms int frmeTime = 0; // frame period, ms (~36ms) int nvals = 0; // number of values received since last display void setup() { FrSky.begin(9600); Serial.begin(115200); dispTime = millis(); lcd.begin(16, 2); lcd.setCursor(0, 0); lcd.print("FrSky Telemetry"); lcd.setCursor(0, 1); lcd.print("Filip Grano 2015"); frame = 0; index = 0; link = 0; stuff = 0; prevTime = millis(); } void loop() { if (FrSky.available()) { // reading input data next = (byte)FrSky.read(); if (next != 0x7E) if (next == 0x7D) // byte stuffing indicator stuff = 1; // set the flag and discard byte else if (stuff == 0) buff[index++] = next; // normal byte else { buff[index++] = next | 0x20; // byte stuffing set, change next byte stuff = 0; // and reset the flag } else { if (index == 10 || index == 11) { // end byte buff[index] = next; frame = 1; index = 0; } else { // start byte? index = 0; buff[index++] = next; } } if (index >= FRAME_SIZE) index = FRAME_SIZE - 1; // prevent buffer overflow } if (buff[1] == FRAME_RVLQ && frame == 1) { // second byte 0xFE - Remote Voltage and Link Quality V1[nvals] = buff[2] * 4 * 330.0 / 255; // V1 - Voltage, up to 13.2V, Internal divider 1:4 V2[nvals] = buff[3] * (22 + 100) / 22 * 330.0 / 255; // V2 - Voltage, up to 18.3V Rx[nvals] = buff[4]; // Up Link Quality RSSI (min 36, max 116-121) Tx[nvals] = buff[5] / 2; // Down Link Quality RSSI (min 36, max 116-121) frmeTime = millis() - prevTime; // frame period in ms prevTime = millis(); frame = 0; link = 1; // valid data received nvals++; } if (link == 1 && millis() > dispTime + DISP_INTERVAL && nvals > 0) { dispTime = millis(); #ifdef DEBUG printData(); #endif lcd.setCursor(0, 0); lcd.print(mode(V1, nvals) / 100.0, 2); lcd.print("V "); lcd.setCursor(7, 0); lcd.print("RX="); lcd.print(mode(Rx, nvals), 1); lcd.print("dBc "); lcd.setCursor(0, 1); lcd.print(mode(V2, nvals) / 100.0, 2); lcd.print("V "); lcd.setCursor(7, 1); lcd.print("TX="); lcd.print(mode(Tx, nvals), 1); lcd.print("dBc "); nvals=0; } } void printData(void) { Serial.print(prevTime / 1000.0, 4); Serial.print(": "); #ifdef DEBUG_HEX for (byte i = 0; i <= 10; i++) { Serial.print(buff[i], HEX); Serial.print(" "); } #endif Serial.print("V1 = "); Serial.print(mode(V1, nvals) / 100.0, 2); Serial.print("V, V2 = "); Serial.print(mode(V2, nvals) / 100.0, 2); Serial.print("V, Rx = "); Serial.print(mode(Rx, nvals)); Serial.print("dBc, Tx = "); Serial.print(mode(Tx, nvals)); Serial.print("dBc, packets = "); Serial.print(nvals); Serial.println(); } int mode(int arr[], int asize) { if (asize==0) { return 0; } int mode = arr[asize-1]; int mcount = 1; int count = 0; for(int i=asize; i>0; i--) { int val = arr[i-1]; for(int j=i; j>0; j--) { if(arr[j-1] == val) count++; } if (count > mcount) { mode = val; mcount = count; } count = 0; } return mode; } |
Used this forum post as a place to start.
Hello~
Note has been modified so that it can see the data to a computer serial port your source
But not good.
Do check is possible?
————————————
#include
#define DE_BUG // Change this to #define DEBUG if needed
#define DE_BUG_HEX
#define FRS_TX_PIN A2 // not used
#define FRS_RX_PIN A3 // telemetry data
#define FRAME_SIZE 12 // max 12 bytes
#define FRAME_RVLQ 0xFE // second byte 0xFE – Remote Voltage and Link Quality
#define FRAME_USER 0xFD // second byte 0xFD – User Data
#define DISP_INTERVAL 500 // ms
SoftwareSerial FrSky = SoftwareSerial(FRS_TX_PIN, FRS_RX_PIN, true); // orig false
byte next = 0;
byte buff[FRAME_SIZE]; // frame array
byte index = 0; // index in frame array
byte link = 0; // link established, data received
byte frame = 0; // frame received indicator
byte stuff = 0; // byte stuffing indicator
int Rx[DISP_INTERVAL/15]; // Up Link Quality RSSI
int Tx[DISP_INTERVAL/15]; // Down Link Quality RSSI
int V1[DISP_INTERVAL/15]; // Port 1 voltage, V * 100
int V2[DISP_INTERVAL/15]; // Port 2 voltage, V * 100
unsigned long dispTime = 0; // time when info was updated, ms
unsigned long prevTime = 0; // time when 0xFE frame was received, ms
int frmeTime = 0; // frame period, ms (~36ms)
int nvals = 0; // number of values received since last display
void setup() {
FrSky.begin(9600);
Serial.begin(9600);
dispTime = millis();
frame = 0;
index = 0;
link = 0;
stuff = 0;
prevTime = millis();
}
void loop() {
if (FrSky.available()) { // reading input data
next = (byte)FrSky.read();
if (next != 0x7E)
if (next == 0x7D) // byte stuffing indicator
stuff = 1; // set the flag and discard byte
else if (stuff == 0)
buff[index++] = next; // normal byte
else {
buff[index++] = next | 0x20; // byte stuffing set, change next byte
stuff = 0; // and reset the flag
}
else {
if (index == 10 || index == 11) { // end byte
buff[index] = next;
frame = 1;
index = 0;
} else { // start byte?
index = 0;
buff[index++] = next;
}
}
if (index >= FRAME_SIZE)
index = FRAME_SIZE – 1; // prevent buffer overflow
}
if (buff[1] == FRAME_RVLQ && frame == 1) { // second byte 0xFE – Remote Voltage and Link Quality
V1[nvals] = buff[2] * 4 * 330.0 / 255; // V1 – Voltage, up to 13.2V, Internal divider 1:4
V2[nvals] = buff[3] * (22 + 100) / 22 * 330.0 / 255; // V2 – Voltage, up to 18.3V
Rx[nvals] = buff[4]; // Up Link Quality RSSI (min 36, max 116-121)
Tx[nvals] = buff[5] / 2; // Down Link Quality RSSI (min 36, max 116-121)
frmeTime = millis() – prevTime; // frame period in ms
prevTime = millis();
frame = 0;
link = 1; // valid data received
nvals++;
}
if (link == 1 && millis() > dispTime + DISP_INTERVAL && nvals > 0) {
dispTime = millis();
#ifdef DEBUG
printData();
#endif
}
Serial.print(“V1 = “);
Serial.print(mode(V1, nvals) / 100.0, 2);
Serial.print(“V, V2 = “);
Serial.print(mode(V2, nvals) / 100.0, 2);
Serial.print(“V, Rx = “);
Serial.print(mode(Rx, nvals));
Serial.print(“dBc, Tx = “);
Serial.print(mode(Tx, nvals));
Serial.print(“dBc, packets = “);
Serial.print(nvals);
Serial.println();
}
void printData(void) {
Serial.print(prevTime / 1000.0, 4);
Serial.print(“: “);
#ifdef DEBUG_HEX
for (byte i = 0; i 0; i–) {
int val = arr[i-1];
for(int j=i; j>0; j–) {
if(arr[j-1] == val) count++;
}
if (count > mcount) {
mode = val;
mcount = count;
}
count = 0;
}
return mode;
}