Browse Source

Fixed to SBUS using software serial

master
Englebert 3 years ago
parent
commit
10865f04b3
  1. 27
      DRAFT.md
  2. 7
      platformio.ini
  3. 37
      src/main.cpp
  4. 4
      src/main.h
  5. 124
      src/sbus.cpp
  6. 25
      src/sbus.h

27
DRAFT.md

@ -1,25 +1,12 @@
.0000000062
mmmuuunnnp
6.2nS per cpu cycle
100000 baud ?
1/100000 = .0000100000
.0000100000
mmmuuunnn
10uS per bit
HIGH:
80% HIGH 20% LOW
LOW:
50% HIGH 50% LOW
GAP:
1.4345ms - 1.4455ms = 0.011ms = 11uS = 1774.1935483870 cpu cycles
10uS ~ 1612.9032258064 cpu cycles
HIGH:
1290.3225806451 HIGH 322.5806451612 LOW
LOW:
806.4516129032 HIGH 806.4516129032 LOW
200000 BAUDRATE (8E2)
[ START BIT ][ DATA BITS x 8 ][ PARITY BITS ][STOP BITS x 2]
.0000050000s = 5uS each pulse of bit ~ 5uS Start Bit + 40uS total time data bits + 5uS Parity Bits + 10uS Stop Bits = 60uS
Total Bit Duration = 60uS = 9677.4193548387 CPUCYCLES
Each Bit Pulse at 806.4516129032 CPUCYCLES

7
platformio.ini

@ -12,9 +12,10 @@
platform = espressif8266
board = esp12e
framework = arduino
; Comment out if upload via USB. Now is via OTA
upload_protocol = espota
upload_port = 192.168.4.1
upload_port = 192.168.4.1
board_build.filesystem = littlefs
board_build.f_cpu = 160000000L
lib_deps = arkhipenko/TaskScheduler@^3.6.0
lib_deps =
arkhipenko/TaskScheduler@^3.6.0
plerup/EspSoftwareSerial@^6.16.1

37
src/main.cpp

@ -14,18 +14,23 @@
#include <TaskScheduler.h>
#include "main.h"
#define LED_STATUS 14
#define LED_HEARTBEAT 2
bool led_heartbeat_state = false;
//// uint16_t rcCommand[18]; // Signal to ESC
// Profiling
int16_t sbus_packets_sent = 0;
int16_t sbus_packets_sent_raw = 0;
int16_t nrf_packets_received = 0;
int16_t nrf_packets_received_raw = 0;
Scheduler scheduler;
RXMessage rxMessage;
// Every 5 miliseconds
Task task_sbus_generator(10, TASK_FOREVER, &send_sbus);
Task task_rx(50, TASK_FOREVER, &nrf_rx);
// Every 7 miliseconds
Task task_sbus_generator(7, TASK_FOREVER, &send_sbus);
// Every 8 millseconds
Task task_rx(8, TASK_FOREVER, &nrf_rx);
// Every 200 miliseconds
Task task_web(200, TASK_FOREVER, &web_handler);
@ -47,7 +52,6 @@ void setup() {
Serial.printf("CPU: %d MHz\r\n", ESP.getCpuFreqMHz());
// Setting up status led
pinMode(LED_STATUS, OUTPUT);
pinMode(LED_HEARTBEAT, OUTPUT);
// Starting up storage
@ -114,35 +118,25 @@ void status_heartbeat(void) {
led_heartbeat_state = !led_heartbeat_state;
if(led_heartbeat_state) {
GPOS = (1 << LED_HEARTBEAT);
GPOS = (1 << LED_STATUS);
} else {
GPOC = (1 << LED_HEARTBEAT);
GPOC = (1 << LED_STATUS);
}
/*****
gpio_count = 0;
profile_start = millis();
while((uint32_t)(millis() - profile_start) < 1000) {
GPOS = (1 << LED_STATUS);
GPOC = (1 << LED_STATUS);
gpio_count++;
}
Serial.println(gpio_count);
****/
}
// Keep sending SBUS
void send_sbus(void) {
sbus.writePackets();
sbus_packets_sent_raw++;
}
uint32_t uptime_total = 0;
void uptime_tracker(void) {
uptime_total++;
sbus_packets_sent = sbus_packets_sent_raw;
sbus_packets_sent_raw = 0;
nrf_packets_received = nrf_packets_received_raw;
nrf_packets_received_raw = 0;
}
@ -226,6 +220,7 @@ void nrf_rx(void) {
sbus.rcCommand[ROLL] = ((rxMessage.Byte05 & 0x07) << 8) | rxMessage.Byte06; // Roll
sbus.signalNotOK = false;
nrf_packets_received_raw++;
last_receive = millis();
}
}

4
src/main.h

@ -9,6 +9,7 @@
const uint64_t pipeIn = 0xE8E8F0F0E1LL; // Must be same as the transmission
// Enable type of microcontroller for the nrf24l01 library to compile.
// #define ESP32
#define ESP12E
@ -30,5 +31,8 @@ void web_handler(void);
void ota_handler(void);
void uptime_tracker(void);
extern int16_t sbus_packets_sent;
extern int16_t nrf_packets_received;
#endif

124
src/sbus.cpp

@ -18,9 +18,6 @@
uint rcChannels[SBUS_CHANNEL_NUMBER];
uint32_t sbusTime = 0;
uint32_t counter = 900;
uint32_t last_count = 0;
SoftwareSerial swSer1;
SBUS::SBUS(void) {
@ -34,9 +31,8 @@ void SBUS::begin(void) {
// swSer1.begin(200000, SWSERIAL_8E2, SBUS_PORT, SBUS_PORT, false, 264);
// swSer1.begin(100000, SWSERIAL_8E2, SBUS_PORT, SBUS_PORT);
swSer1.begin(200000, SWSERIAL_8E2, SBUS_PORT, SBUS_PORT);
//// swSer1.enableTx(true);
//// swSer1.enableIntTx(true);
swSer1.enableTx(true);
swSer1.enableIntTx(true);
// Initialize to 1000
for(uint8_t i = 0; i < SBUS_CHANNEL_NUMBER; i++) {
@ -48,10 +44,12 @@ void SBUS::run(void) {
}
uint32_t last_profile = 0;
uint32_t total_high = 0;
uint32_t total_low = 0;
// Sending SBUS packets
void SBUS::writePackets(void) {
if((uint32_t)(millis() - sbusTime) > SBUS_UPDATE_RATE) {
// if((uint32_t)(millis() - sbusTime) > SBUS_UPDATE_RATE) {
if(signalNotOK) {
// DEBUG ONLY...later put back to 900
// rcChannels[2] = 900;
@ -70,20 +68,23 @@ void SBUS::writePackets(void) {
swSer1.write(sbusPacket, SBUS_PACKET_LENGTH);
// Looping through the bytes - Generating Parity Bits
// Is using SBUS_FAST (200000 Baud), 8E2 (Even Parity and 2 bits stop
// For sending at 200000 baud, each bit used about 5uS
// Profiling each bits timing before sending
// // Looping through the bytes - Generating Parity Bits
// // Is using SBUS_FAST (200000 Baud), 8E2 (Even Parity and 2 bits stop
// // For sending at 200000 baud, each bit used about 5uS
// // Profiling each bits timing before sending
// uint32_t clock_cycles = 0;
//
// if((uint32_t)(millis() - last_profile) > 500) {
// Serial.printf("Cmd: %d Signal: %d\r\n", rcCommand[2], signalNotOK);
// last_profile = millis();
// }
if((uint32_t)(millis() - last_profile) > 500) {
Serial.printf("Cmd: %d Signal: %d Sent: %d NRF: %d\r\n", rcCommand[2], signalNotOK, sbus_packets_sent, nrf_packets_received);
last_profile = millis();
}
//
// total_high = 0;
// total_low = 0;
//
// // bool tx_state = true;
// uint8_t parity_count = 0;
// uint8_t data_bits = 0;
// int8_t data_bits = 0;
// bool current_bit = 0;
//
// // Now we roughly know how much per clock cycles per microseconds
@ -94,105 +95,99 @@ void SBUS::writePackets(void) {
//
// // START BIT - For 1 clock cycle = 5uS = clock_per_micro
// // Set to LOW as start bit
// GPOS = (1 << SBUS_PORT);
//
// // Low for 50% duty cycle
// for(clock_cycles = 0; clock_cycles < PULSE_LOW_ON_TIME; clock_cycles++);
//
// GPOC = (1 << SBUS_PORT);
// delay_cycles(PULSE_BIT_TIME);
//
// GPOS = (1 << SBUS_PORT);
// delay_cycles(PULSE_GAP);
//
// // High for 50% duty cycle
// for(clock_cycles = 0; clock_cycles < PULSE_LOW_OFF_TIME; clock_cycles++);
//
// // DATA FRAME
// // Reading the data sending it byte by byte
// ///// for(data_bits = 7; data_bits >= 0; data_bits--) {
// for(data_bits = 0; data_bits < 8; data_bits++) {
// current_bit = (sbusPacket[pos] >> data_bits) & 0x01;
//
// // Sending it out...
// if(current_bit) {
// if(current_bit == 0x01) {
// parity_count++;
//
// total_high++;
//
// // HIGH
// GPOS = (1 << SBUS_PORT);
// for(clock_cycles = 0; clock_cycles < PULSE_HIGH_ON_TIME; clock_cycles++);
//
// // LOW
// GPOC = (1 << SBUS_PORT);
// for(clock_cycles = 0; clock_cycles < PULSE_HIGH_OFF_TIME; clock_cycles++);
//
// delay_cycles(PULSE_BIT_TIME);
//
// } else {
// // HIGH
// GPOS = (1 << SBUS_PORT);
// for(clock_cycles = 0; clock_cycles < PULSE_LOW_ON_TIME; clock_cycles++);
//
// // LOW
// total_low++;
//
// GPOC = (1 << SBUS_PORT);
// for(clock_cycles = 0; clock_cycles < PULSE_LOW_OFF_TIME; clock_cycles++);
// delay_cycles(PULSE_BIT_TIME);
// }
//
// // GAP
// GPOS = (1 << SBUS_PORT);
// delay_cycles(PULSE_GAP);
// }
//
// // PARITY BITS
// // Parity Calculation
// if(parity_count & 0x01) {
// if((parity_count & 0x01) == 0x01) {
// // ODD
// // Need to make it EVEN....
// // HIGH
// GPOS = (1 << SBUS_PORT);
// for(clock_cycles = 0; clock_cycles < PULSE_HIGH_ON_TIME; clock_cycles++);
// delay_cycles(PULSE_BIT_TIME);
//
// // LOW
// GPOC = (1 << SBUS_PORT);
// for(clock_cycles = 0; clock_cycles < PULSE_HIGH_OFF_TIME; clock_cycles++);
// } else {
// // EVEN
// // Nothing needs to be set
// // HIGH
// GPOS = (1 << SBUS_PORT);
// for(clock_cycles = 0; clock_cycles < PULSE_LOW_ON_TIME; clock_cycles++);
//
// // LOW
// GPOC = (1 << SBUS_PORT);
// for(clock_cycles = 0; clock_cycles < PULSE_LOW_OFF_TIME; clock_cycles++);
// delay_cycles(PULSE_BIT_TIME);
// }
//
// // STOP BITS
// // HIGH
// // GAP
// GPOS = (1 << SBUS_PORT);
// for(clock_cycles = 0; clock_cycles < PULSE_LOW_ON_TIME; clock_cycles++);
// delay_cycles(PULSE_GAP);
//
// // STOP BITS
// // LOW
// GPOC = (1 << SBUS_PORT);
// for(clock_cycles = 0; clock_cycles < PULSE_LOW_OFF_TIME; clock_cycles++);
// delay_cycles(PULSE_BIT_TIME);
//
// // HIGH
// // GAP
// GPOS = (1 << SBUS_PORT);
// for(clock_cycles = 0; clock_cycles < PULSE_LOW_ON_TIME; clock_cycles++);
// delay_cycles(PULSE_GAP);
//
// // LOW
// GPOC = (1 << SBUS_PORT);
// for(clock_cycles = 0; clock_cycles < PULSE_LOW_OFF_TIME; clock_cycles++);
// delay_cycles(PULSE_BIT_TIME);
//
//
// // GAP
// GPOS = (1 << SBUS_PORT);
// delay_cycles(PULSE_GAP);
// }
//
// Wait for next round
sbusTime = millis();
}
// sbusTime = millis();
// }
}
// Preparing SBUS packets
void SBUS::sbusPreparePacket(uint16_t channels[], bool isSignalLoss, bool isFailsafe){
if(millis() - last_count > 2000) {
counter+= 100;
if(counter > 2000) {
counter = 900;
}
// Delay CPU Cycles
void SBUS::delay_cycles(uint16_t cpucycles) {
uint32_t cpucycle_start = ESP.getCycleCount();
while((uint32_t)(ESP.getCycleCount() - cpucycle_start) < cpucycles) {}
}
last_count = millis();
}
// Preparing SBUS packets
void SBUS::sbusPreparePacket(uint16_t channels[], bool isSignalLoss, bool isFailsafe){
static int output[SBUS_CHANNEL_NUMBER] = {0};
/*
@ -201,9 +196,6 @@ void SBUS::sbusPreparePacket(uint16_t channels[], bool isSignalLoss, bool isFail
*/
for(uint8_t i = 0; i < SBUS_CHANNEL_NUMBER; i++) {
output[i] = map(channels[i], RC_CHANNEL_MIN, RC_CHANNEL_MAX, SBUS_MIN_OFFSET, SBUS_MAX_OFFSET);
// DEBUG oNly
// output[i] = 1200;
// output[i] = counter;
}
uint8_t stateByte = 0x00;

25
src/sbus.h

@ -1,6 +1,20 @@
#ifndef SBUS_H_
#define SBUS_H_
// #define SBUS_MIN_OFFSET 173
// #define SBUS_MID_OFFSET 992
// #define SBUS_MAX_OFFSET 1811
// #define SBUS_CHANNEL_NUMBER 16
// #define SBUS_PACKET_LENGTH 25
// #define SBUS_FRAME_HEADER 0x0f
// #define SBUS_FRAME_FOOTER 0x00
// #define SBUS_FRAME_FOOTER_V2 0x04
// #define SBUS_STATE_FAILSAFE 0x08
// #define SBUS_STATE_SIGNALLOSS 0x04
// #define SBUS_UPDATE_RATE 15 // ms
// #define SBUS_PORT 16 // Trigger pulse from the port
// FAST SBUS TIMING (Theoritically 50% timing)
#define SBUS_MIN_OFFSET 173
#define SBUS_MID_OFFSET 992
#define SBUS_MAX_OFFSET 1811
@ -14,15 +28,10 @@
#define SBUS_UPDATE_RATE 15 // ms
#define SBUS_PORT 16 // Trigger pulse from the port
// For BAUD RATE: 100000
#define PULSE_HIGH_ON_TIME 1290
#define PULSE_HIGH_OFF_TIME 323
#define PULSE_LOW_ON_TIME 807
#define PULSE_LOW_OFF_TIME 807
#define PULSE_TOTAL_TIME 1613
#include <Arduino.h>
#include "SoftwareSerial.h"
#include "main.h"
#include <SoftwareSerial.h>
class SBUS {
public:
@ -36,6 +45,8 @@ class SBUS {
void run(void);
void sbusPreparePacket(uint16_t channels[], bool isSignalLoss, bool isFailsafe);
void writePackets(void);
void delay_cycles(uint16_t cpucycles);
private:
uint32_t last_wifi_check, wifi_check_duration;

Loading…
Cancel
Save