Das zweite Leben von RC-Modellen, also die Fernbedienung von Frog_Qmak

Hallo
Ich möchte eine universelle Plattform zum Betrieb ferngesteuerter Modelle vorstellen und teilen.
Ich habe viele Jahre lang nichts im Forum gepostet – das bedeutet nicht, dass nichts passiert ist, aber es hat sich nicht immer gelohnt, es zu zeigen.

Alles begann damit, dass ich etwas machen wollte, das mir Spaß macht und mich dazu inspiriert, mit Kabeln und Arduino herumzuspielen. Also bestellte ich ein Panzerfahrgestell bei einem chinesischen Online-Shop (sinoning.com) und so begann das Abenteuer. Nach dem Panzer kam ein Miniauto (ebenfalls aus demselben Laden) und dann wurde für 1/3 des Wertes von Neufahrzeugen, ein vollwertiges Auto mit 4x4-Antrieb und ein ferngesteuertes Schnellboot, bei Allegro als "beschädigt" gekauft. Der Schaden am Auto bestand darin, dass Wasser in das Innere eindrang und den Motor blockierte (das Auto ist theoretisch wasserdicht, verfügt über einen positiven Auftrieb und kann sich auch auf dem Wasser "bewegen"), der wiederbelebt wurde (durch Gewalt und anschließendes Drehen von Hand). Am Boot war theoretisch die Steuerung beschädigt, aber ich habe nicht überprüft, was passiert ist, weil ich von Anfang an meine eigene installieren wollte.
Ein paar Worte zur Steuerung selbst:
Die Fernbedienung besteht aus 2 Joysticks (Arduino-Modulen), Arduino Nano, Li-Ion-Akku, BMS-System, 5V-Aufwärtswandler und Radio (HC-12-Modul). Keine rocket science. Ich hatte ein großes Problem bei der Diagnose des Problems, dass das BMS die Batterie nicht laden wollte – die Diode blinkte sehr schnell, als ob irgendwo kein Kontakt bestand oder im Modul Rückkopplung auftritt. In meiner Verzweiflung habe ich es direkt an die Batterie gelötet (vorher über den Schalter) und damit war das Problem gelöst. Ich weiß nicht, warum der Schalter solche Probleme verursachte - vielleicht stellten die Kontakte einen elektrischen Widerstand dar und das Modul wurde z. B. durch das Radio oder den Konverter erregt. Die Fernbedienung verfügt über zwei Modi (der Modus wird durch langes Drücken des linken Joysticks geändert): Auto-/Bootsmodus (Standard: linker Joystick vorwärts/rückwärts, rechter Joystick rechts/links) und Panzermodus (beide vordere/hintere Joysticks zur Differenzialsteuerung). ). Durch kurzes Halten des linken Joysticks ändert sich der Lampenmodus (hell/mittel/aus) im großen Auto.
Die Empfänger bestehen auch aus Arduino Nano, HC-12, sowie (Autos, Panzer) BMS und einer H-Brücke zur Steuerung der Motoren (beim Boot zur Steuerung des Motors, das Ruder wird durch ein Servo betrieben). Das kleinste Auto wird von einer LI-ION-Zelle und einem STEP-UP-Wandler angetrieben, daher der große Kondensator, damit Spannungsabfälle den Arduino nicht zurücksetzen. Die restlichen Modelle laufen mit zwei 18650 (das große Auto hat auch einen Kondensator am Stromversorgung, der aber nicht benötigt wird).
Weitere Informationen
Das große Auto verfügt über Lichter auf Basis von WS2812B (zwei weiße vorne, ein rotes hinten).
Bootssteuerung ist komplizierter, da der „normale PWM-Code“ nicht zum Betrieb des Servos verwendet werden kann, da dies auf andere Weise erfolgt. Alle Empfänger haben einen identischen Code; Beim Start prüft Arduino, ob an einem der Pins die entsprechende Spannung anliegt (versorgt vom 3,3-V-Ausgang) und aktiviert in diesem Fall den „Bootsmodus“. Bei anderen Modellen ist dieser Pin nicht gebrückt – so ist das Programm universell und es ist nicht nötig, einen weiteren „Modus“ in der Fernbedienung hinzuzufügen.
Das Boot verfügt über einen Schutz gegen niedrige Batteriespannung – er wird über einen Spannungsteiler gemessen und verfügt über zwei Aktivierungsschwellen. Bei Erreichen der ersten Stufe ertönt für einige Sekunden ein akustisches Signal (5V-Summer, gesteuert durch den BS170-Transistor). Bei Erreichen der zweiten Stufe schaltet sich das akustische Signal dauerhaft ein und die Motorleistung wird reduziert (PWM max 50 %). Das in den Werkszellen verwendete BMS unterbricht den Strom auch bei Tiefentladung nicht, was Sinn macht, denn es ist besser, die Batterien zu zerstören, als das Boot 10 Meter vom Ufer entfernt festzustecken.
Die Steuerung des Servos erfolgt über eine Softwarebibliothek. Dies liegt daran, dass die Standard-Servobibliothek einen Konflikt mit der Bibliothek hatte, die für die Steuerung des WS2812 verantwortlich ist (wahrscheinlich ein Konflikt aufgrund der Verwendung desselben Timers).
[F]
Das Programm verfügt auch über kommentierte Abschnitte zum Testen der Batterie im Boot. Bevor ich feststellte, dass das BMS sie nicht abschaltete, schrieb ich ein Skript, das die niedrigste gemessene Versorgungsspannung im EEPROM speicherte und nach dem Anschließen des Arduino an den Computer verschickte es über Serial. Ich wollte wissen, bis zu welchem Grad die Zellen entladen werden könnten, um die Schutzschwellen richtig einzustellen, aber das erwies sich als unnötig.
Die Fernbedienung und das große Spielzeugauto verfügen über Anschlüsse zum Laden der Batterien; für ein kleines Auto und das Boot gibt es Ladegeräte.
Im Allgemeinen habe ich festgestellt, dass die „Spiral“-Antenne im Sender schlecht funktioniert, ein normaler Draht geeigneter Länge funktioniert jedoch gut. Die Antennen in der Fernbedienung und im Auto sind in Goldstiftfassungen montiert, so dass sie zum Transport leicht abgenommen werden können. Das Boot verfügt standardmäßig über eine Spiralantenne. HC-12-Funkgeräte sind sehr cool, die theoretische Reichweite (bei niedriger Bitrate, direkte Sicht) beträgt bis zu einem Kilometer. Ich füge zwei Dokumente bei, die für ihre Bedienung nützlich sein werden – sie enthalten eine Beschreibung der Funktionen und Konfiguration.
Kalibrierung wird benötigt, um den Code an einen gegebenen Joystick (Neutralpunkt) und Servo (auch) anzupassen. Die Werte sind in den Kommentaren beschrieben.
Ich habe keine Schaltpläne, aber ich denke, dass man anhand der Beschreibungen und Fotos leicht herausfinden kann, wo es langgeht. Ich weiß, dass es (besonders bei der Fernbedienung) ein Spinnennetz aus Kabeln gibt, aber ich verschwende meine Zeit nicht mit dem Entwerfen von Platinen, ich genieße Elektronik und das Schreiben von Programmen.
Der Code ist stark kommentiert (auf Englisch), sodass das Verständnis der Programme kein Problem darstellen sollte. Die Reichweite in der gewählten Konfiguration (Funkbitrate, Antenne) beträgt mindestens 200 m (vielleicht mehr, habe ich nicht überprüft, bei einer solchen Entfernung ist es schwierig, das Modell zu steuern).
Wenn es jemanden interessiert, lohnt es sich, dieses Thema zu verfolgen. Wenn es ein Update der Programme gibt, werde ich es hinzufügen.
Unten findet man die Fotos und den Code.









SENDER
// delay(1);//It is necessary for proper message sending. Without this messages sometimes are merged.
//$$ separates values, ! ends the message
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //RX, TX
//L: 3-507-1017 --> 1020 for smooth operation [506;508]
//R: 3-526-1017 --> 1020 for smooth operation [525;527]
//STEER [R]: 0-517-1022 [521;523]
int ax; //analog read joystick A
byte af; //analog joystick A forward
byte ab; //analog joystick A backward
int bx; //analog read joystick B
byte bf; //analog joystick B forward
byte bb; //analog joystick B backward
boolean mode = false; //Tank or Car mode (default: car)
int buttontest; //conunting time of button being pressed
String toSend;
void setup()
{
pinMode(4, OUTPUT);
pinMode(12, OUTPUT);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
digitalWrite(4, HIGH); //DISABLE AT MODE
digitalWrite(12, HIGH);//RIGHT JOYSTICK VCC
digitalWrite(11, LOW);//RIGHT JOYSTICK GND
digitalWrite(10, HIGH);//LEFT JOYSTICK VCC
digitalWrite(9, LOW);//LEFT JOYSTICK GND
digitalWrite(5, LOW);//BUZZER GND
digitalWrite(6, LOW);//BUZZER VCC
pinMode(A0, INPUT); //LEFT JOYSTICK BUTTON
pinMode(A1, INPUT); //RIGHT JOYSTICK BUTTON
pinMode(A5, INPUT); //RIGHT JOYSTICK FORWARD & BACKWARD
pinMode(A6, INPUT); //RIGHT JOYSTICK RIGHT & LEFT
pinMode(A2, INPUT); //LEFT JOYSTICK FORWARD & BACKWARD
Serial.begin(9600);
pinMode(4, OUTPUT); //for MODE setup
digitalWrite(4, LOW); //ENTER AT MODE
delay(50);//necessary to wait after mode change
mySerial.begin(9600);//9600 adjust after adjusting communication speed using AT+BXXX
mySerial.println("AT+FU3");
delay(50);
mySerial.println("AT+B9600");//9600
delay(50);
mySerial.println("AT+RX"); //AT MODE REQUIRED TO BE ON (4 LOW)
delay(100);
digitalWrite(4, HIGH); //EXIT AT MODE
delay(50);//necessary to wait after mode change
}
void loop()
{
//RESET OLD VALUES TO AVOID CONFLICTS
af = 0;
ab = 0;
bf = 0;
bb = 0;
////////////////////////////////STEERING MODE CHECK
if (analogRead(A0) < 10) //BUTTON PRESSED
{
buttontest = buttontest + 1; //COUNTING TIME OF BUTTON BEING PRESSED
mySerial.print("BUTTON PRESSED !");
Serial.println("BUTTON PRESSED !");
}
else
{
buttontest = 0; //RESET IN CASE OF ACCIDENTAL CLICK
}
//Serial.println(buttontest);
if (buttontest == 40 ) //BUTTON PRESSED - SENT LIGHT ADJUST SIGNAL
{
toSend = String("E") + "!";
mySerial.print(toSend);
delay(1);
digitalWrite(6, HIGH);
delay(100);
digitalWrite(6, LOW);
delay(100);
digitalWrite(6, HIGH);
delay(100);
digitalWrite(6, LOW);
delay(1000);
}
if (buttontest == 41) //BUTTON PRESSED - SENT LIGHT ON/OFF SIGNAL
{
toSend = toSend = String("F") + "!";
mySerial.print(toSend);
delay(1);
digitalWrite(6, HIGH);
delay(1000);
digitalWrite(6, LOW);
}
if (buttontest >= 42) //BUTTON PRESSED - CHANGE TO TANK MODE
{
mode = !mode;
buttontest = 0;
mySerial.print("MODE CHANGED !");
delay(1);
Serial.println("MODE CHANGED !");
digitalWrite(6, HIGH);
delay(4000);
digitalWrite(6, LOW);
}
////////////////////////////////////////LEFT JOYSTICK READ & CALCULATE
ax = analogRead(A2); //LEFT JOYSTICK
// if (mode == 1)
// {
// Serial.print("A2 LEFT: ");
// Serial.println(ax);
// }
// else
// {
// Serial.print("A2 MOVE: ");
// Serial.println(ax);
// }
//Serial.print("AX READ: ");
//Serial.println(ax);
//af is PWM for A engine forward
if (ax > 508)
{
af = map(ax, 508, 1020, 0, 255); //af is PWM for A engine forward
//Serial.print("LEFT FORWARD: ");
//Serial.println(af);
toSend = "A" + String(af, DEC) + "!";
mySerial.print(toSend);
delay(5);
}
if (ax >= 506 && ax <=508) //to send zero command in case of neutral joistick position
{
toSend = "A" + String(0, DEC) + "!";
mySerial.print(toSend);
delay(5);
toSend = "B" + String(0, DEC) + "!";
mySerial.print(toSend);
delay(5);
}
if (ax < 506)
{
ab = map(ax, 3, 506, 255, 0); //ab is PWM for A engine backward
//Serial.print("LEFT BACKWARD: ");
//Serial.println(ab);
toSend = "B" + String(ab, DEC) + "!";
mySerial.print(toSend);
delay(5);
}
////////////////////////////////END OF LEFT JOYSTICK READ & CALCULATE
////////////////////////////////////////RIGHT JOYSTICK READ & CALCULATE
///////////READING POSITION FROM CORRECT JOYSTICK OUTPUT
if (mode == 1)
{
bx = analogRead(A5); //IF IN TANK MODE
// Serial.print("A5 RIGHT: ");
// Serial.println(bx);
}
else
{
bx = analogRead(A4); //IF IN CAR MODE
//Serial.print("A6 STEER: ");
//Serial.println(bx);
}
///////////END OF READING FROM CORRECT JOYSTICK OUTPUT
///////////CALCULATING PWM ACCORDING TO
//JOYSTICK'S ZERO CALIBRATION POSITION
if (mode == 1) //IF IN TANK MODE
{
if (bx > 527)
{
bf = map(bx, 527, 1020, 0, 255); // bf is PWM for B engine forward
//Serial.print("RIGHT FORWARD: ");
//Serial.println(bf);
toSend = "C" + String(bf, DEC) + "!";
mySerial.print(toSend);
delay(5);
}
if (bx < 525)
{
bb = map(bx, 3, 527, 255, 0); //bb is PWM for B engine backward
//Serial.print("RIGHT BACKWARD: ");
//Serial.println(bb);
toSend = "D" + String(bb, DEC) + "!";
mySerial.print(toSend);
delay(5);
}
}
else //IF IN CAR MODE
{
if (bx > 517)
{
bf = map(bx, 517, 1022, 0, 255); //bf is PWM for B engine forward
//Serial.print("STEER RIGHT: ");
//Serial.println(bf);
toSend = "C" + String(bf, DEC) + "!";
mySerial.print(toSend);
//Serial.println(toSend);
delay(5);
}
if (bx >= 516 && bx <=517) //to send zero command in case of neutral joistick position
{
toSend = "C" + String(0, DEC) + "!";
mySerial.print(toSend);
delay(5);
toSend = "D" + String(0, DEC) + "!";
mySerial.print(toSend);
delay(5);
}
if (bx < 516)
{
bb = map(bx, 0, 517, 255, 0); //bb is PWM for B engine backward
//Serial.print("STEER LEFT: ");
//Serial.println(bb);
toSend = "D" + String(bb, DEC) + "!";
mySerial.print(toSend);
//Serial.println(toSend);
delay(5);
}
}
////////////////RIGHT JOYSTICK DIAG
//Serial.print("AX: ");
//Serial.println(ax);
//Serial.print("BX: ");
//Serial.println(bx);
/////////////////////////////////END OF LEFT JOYSTICK READ & CALCULATE
}// END OF LOOP
EMPFÄNGER
#include <SoftwareSerial.h>
#include <Adafruit_NeoPixel.h>
//#include <EEPROM.h>
#include <PWMServo.h>//software PWM used because servo library had conflict with other used functions using PWM generated by the same internal closk
PWMServo myservo; // create servo object to control a servo
SoftwareSerial mySerial(2, 3); //RX, TX
Adafruit_NeoPixel
strip = Adafruit_NeoPixel(3, 13, NEO_GRB + NEO_KHZ800); //NO of pixels, PIN
byte af, ab, bf, bb;
boolean light = 0; //LIGHT ON/OFF, default = OFF
boolean change = false; // flag to mark change to use WS2812B communication once for light ON/OFF. Constant communication interrupts message receiving
boolean lightadjustment = false; // flag to mark change to use WS2812B communication once for light level adjustment. Constant communication interrupts message receiving
byte xy; //light brightness pre set setting
byte brightness = 64; //brightness level (0-255), default = 64
boolean boatmode;// if true, then boat mode
byte modecount = 0; //no. of successful read sequences
int bootval;// voltage check at boot to detect whether it is a boat or not
byte neutral = 85; //neutral position of servo
byte servoangle; //servo's angle
int serwoPWM;// calculated value to steer servo by generating PWM
unsigned long counter; //time from last message
unsigned long nowtime; //time now. Used further to calculate time past since previous loop
//unsigned long pinginterval; // for signalling range ping messages
float voltageread; //voltage read at input
float batvoltage; //calculated battery level (incl. calculated offset)
byte mediumdischargecount = 0; //to avoid one - time battery voltage drops,alarm will be activated after few times threshold is reached
byte deepdischargecount = 0; //to avoid one - time battery voltage drops,alarm will be activated after few times threshold is reached
long mediumbatlevelalarmtime; //time of buzzer's activation
boolean mediumbatlevelalarmactivation = false;
boolean deepdischargealarmactivation = false;
//int lowestbatvoltage; ////////////////////USED ONLY AT BOOT TO HAVE ANY VALUE FOR IF FUNCTION TO COMPARE TO
//int lowestbatEEPROM;
void setup()
{
//writeIntIntoEEPROM(7000);//EEPROM LOW RESET USED TO START A NEW RECORDING
//PIN D11 BURNT !!!!!!!!!!!!
//PINS A6&A7 cannot be used as analog output in Arduino Nano
pinMode(4, OUTPUT); //AT MODE SWITCH
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(10, OUTPUT);//SERVO
pinMode(13, OUTPUT); //built in led + WS2812B
pinMode(A1, OUTPUT); //GND for voltage sensing
pinMode(A0, INPUT); //voltage check at boot to detect whether it is a boat or not
pinMode(A2, INPUT); //battery voltage check
pinMode(A5, OUTPUT); //low battery buzzer output
digitalWrite(A1, LOW); //GND for voltage sensing
digitalWrite(A5, LOW); //deactivate buzzer
digitalWrite(4, LOW); //ENTER AT MODE
delay(50);//necessary to wait after AT mode change
Serial.begin(9600);
mySerial.begin(9600);//adjust after adjusting communication speed using AT+BXXX
mySerial.println("AT+FU3");
delay(50);
mySerial.println("AT+B9600");
delay(50);
mySerial.println("AT+RX"); //AT MODE REQUIRED TO BE ON (4 LOW)
delay(100);
digitalWrite(4, HIGH); //EXIT AT MODE
delay(50);//necessary to wait after mode change\
analogReference(INTERNAL); //1,1V
modecheck(); //Function to detect whether hardware is a boat or not
analogReference(INTERNAL); //1,1V for battery measurement
if (boatmode == true)
{
myservo.attach(SERVO_PIN_B); //Library works only at PIN9 and 10 (already used)
servostart(); //Sequence for servo movement at boat's boot
testbeep(); //Test buzzer
//Serial.print("LOWEST VOLTAGE FROM EEPROM: ");
//Serial.println(readIntFromEEPROM());
}
else
{
strip.begin(); // INITIALIZE NeoPixel strip object
strip.clear();
strip.show();
startsequence(); //LED BLINK at car's boot
}
} ///////////////////////////////////////////END OF SETUP
void loop()
{
///////////////////////LOST CONNECTION PROTECTION
nowtime = millis();
if ((nowtime - counter) > 1000) //1000 MS SIGNAL LOST TRIGGER
{
//Serial.println(nowtime-counter);
//Serial.println("CONNECTION LOST !!!");
if (boatmode == false) //IF IN CAR MODE
{
digitalWrite(11, LOW);
digitalWrite(10, LOW);
digitalWrite(6, LOW);
digitalWrite(5, LOW);
}
else //IF IN BOAT MODE
{
digitalWrite(6, LOW);
digitalWrite(5, LOW);
}
}
///////////////////////END OF LOST CONNECTION PROTECTION
//////////////////////////100 MS SIGNAL PING TRIGGER
// if ((nowtime - pinginterval) > 50)
// {
// //Serial.println("PING INTERVAL");
// //Serial.println(nowtime-pinginterval);//Loop time
// pinginterval = millis();
// ();
// }
///////////////////////END OF SIGNAL PING TRIGGER
////////////////////////////////////// MESSAGE RECEIVING
while (mySerial.available())
{
static String receivedMessage = ""; // Store the received message
char receivedChar = mySerial.read();
if (receivedMessage.length() == 0)
{
if (receivedChar == 'A' || receivedChar == 'B' || receivedChar == 'C' || receivedChar == 'D')
{
receivedMessage = receivedChar; // Start building the message with the received character
}
if (receivedChar == 'F')
{
light = !light;
change = true; // FLAG FOR LIGHT STATE CHANGE
//Serial.println("LIGHT ON/OFF !");
}
if (receivedChar == 'E')
{
lightadjustment = true; // FLAG FOR LIGHT ADJUSTMENT
}
}//////////////END OF receivedMessage.length() == 0
else
{
if (receivedChar == '!')
{
// Message received and ends with '!'
Serial.println(receivedMessage);//////////////////////////////////////
// Serial.println("MESSAGE RECEIVED, CONNECTION OK!");
counter = millis();
processMessage(receivedMessage, boatmode, neutral, deepdischargealarmactivation);
receivedMessage = ""; // Clear the received message for the next one
}
else
{
receivedMessage += receivedChar;
}
}
}//END OF WHILE
/////////////////////////////////// END OF MESSAGE RECEIVING
////////////////////////////////// LIGHT ON&OFF
if (light == true && change == true) //turn ON the light to the pre set level
{
change = false; //function activated only once
lighton(); // turn ON the light function
}
if (light == false && change == true) //turn OFF the light
{
change = false; //function activated only once
lightoff(); // turn the light OFF function
}
////////////////////////////////// END OF LIGHT ON&OFF
////////////////////////////////// LIGHT LEVEL & ADJUST
if (lightadjustment == true)
{
if (xy == 0)
{
Serial.println("MAX");
strip.setBrightness(255);
strip.show();
xy = 1;
lightadjustment = false;
}
}
if (lightadjustment == true)
{
if (xy == 1)
{
Serial.println("DEFAULT");
strip.setBrightness(64);
strip.show();
xy = 0;
lightadjustment = false;
}
}
////////////////////////////////// END OF LIGHT LEVEL &ADJUST
/////////////////////////////////// VOLTAGE READ AND BUZZER ACTIVATION
if (boatmode == true)
{
voltageread = analogRead(A2);
//Serial.println(voltageread);
batvoltage = 10.88 * (long)voltageread * 1100 / 1024; //Convert voltageread to long to correctly handle multiplication (without int overflow). Voltage appplied through 1/10 divider. 0.88 after 10 for calibration
//Serial.print("READ BATTERY VOLTAGE: ");
//Serial.println(batvoltage);
}
//batvoltage=1.3;// BUZZER & LOW BATTERY PWM TEST
if (batvoltage <= 6.6)
{
if (mediumbatlevelalarmactivation == false) //if medium battery level alarm has not been activated yet
{
mediumdischargecount = mediumdischargecount + 1;
//Serial.print("MEDIUM BAT VOLTAGE COUNT:");
//Serial.println(mediumdischargecount);
}
}
if (batvoltage <= 5.8)
{
if (deepdischargealarmactivation == false) ////if battery deep discharge alarm has not been activated yet
{
deepdischargecount = deepdischargecount + 1;
//Serial.print("DEEP BAT VOLTAGE COUNT:");
//Serial.println(deepdischargecount);
}
}
if (mediumdischargecount == 10) //medium battery level alarm activation
{
if (mediumbatlevelalarmactivation == false) //activate medium battery alarm only once
{
mediumbatlevelalarmtime = millis();
Serial.println("MEDIUM BATTERY LEVEL ALARM !!!");
digitalWrite(A5, HIGH); //activate buzzer
mediumbatlevelalarmactivation = true; //medium battery alarm will not be activated again
}
}
if (((millis() - mediumbatlevelalarmtime) > 10000 && (millis() - mediumbatlevelalarmtime) < 14000) ) //if alarm has been activated for more than 10 seconds but only once
{
digitalWrite(A5, LOW); //turn off the buzzer
}
if (deepdischargecount == 10) //low battery level alarm activation
{
digitalWrite(A5, HIGH); //activate buzzer
if (deepdischargealarmactivation == false)
{
Serial.println("LOW BATTERY LEVEL ALARM !!!"); //send message only once
}
deepdischargealarmactivation = true;
digitalWrite(A5, HIGH); //permanently activate the buzzer
}
/////////////////////////////////// END OF VOLTAGE READ AND BUZZER ACTIVATION
// /////////////////////////////////// VOLTAGE READ AND EEPROM READ&WRITE
// if (boatmode == true)
// {
// voltageread = analogRead(A2);
// Serial.print("ANALOG VOLTAGE: ");
// Serial.println(voltageread);
// batvoltage = 10.88 * (long)voltageread * 1100 / 1024; //Convert voltageread to long to correctly handle multiplication (without int overflow). Voltage appplied through 1/10 divider. 0.88 after 10 for calibration
// Serial.print("READ VOLTAGE: ");
// Serial.println(batvoltage);
//
// if (batvoltage > 3000) //to prevent from reading when battery is not connected (analog pin is grounded by 1k resistor)
// {
// if (batvoltage < lowestbatEEPROM) //if current voltage is lower than the lowest recorded in EEPROM
// {
// lowestbatvoltage = batvoltage;
// writeIntIntoEEPROM(lowestbatvoltage);
// Serial.print("!!!!!! NEW LOWEST VOLTAGE RECORDED: ");
// Serial.println(lowestbatvoltage);
// }
// }
//
// Serial.print("LOWEST VOLTAGE: ");
// Serial.print(lowestbatvoltage);
// Serial.println(" (SINCE BOOT)");
// lowestbatEEPROM = readIntFromEEPROM(); //read lowest battery value stored in EEPROM
// Serial.print("LO BAT EEPROM : ");
// Serial.println(lowestbatEEPROM);
// }/////////////////////////////////// END OF VOLTAGE READ AND EEPROM READ&WRITE
}////////////////////////////////////END OF LOOP
////////////////////////////////////FUNCTIONS///////////////////////////////////////////
///////////////////////////////////////////PROCESS MESSAGE
void processMessage(String receivedMessage, boolean boatmode, byte bootval, boolean deepdischargealarmactivation)
{
//Serial.println(receivedMessage); //////////////////////////////// RECEIVED MESSAGE
if (receivedMessage.charAt(0) == 'A')
{
af = receivedMessage.substring(1).toInt();
}
if (receivedMessage.charAt(0) == 'B')
{
ab = receivedMessage.substring(1).toInt();
}
if (receivedMessage.charAt(0) == 'C')
{
bf = receivedMessage.substring(1).toInt();
}
if (receivedMessage.charAt(0) == 'D')
{
bb = receivedMessage.substring(1).toInt();
}
if (boatmode == false) //////////////////////PWM GENERATION IF IN CAR MODE
{
if (af > 3) //A FORWARD PWM&LOW
{
analogWrite(11, af);
digitalWrite(10, LOW);
}
if (ab > 3) //A BACKWARD PWM&LOW
{
digitalWrite(11, LOW);
analogWrite(10, ab);
}
if (bf > 3) //B FORWARD PWM&LOW
{
analogWrite(6, bf);
digitalWrite(5, LOW);
}
if (bb > 3) //B BACKWARD ENGINE PWM&LOW
{
digitalWrite(6, LOW);
analogWrite(5, bb);
}
if (bf <= 3 && bb <= 3) //FOR ZEROING AS PROGRAM DO NOT ZERO BY DEFAULT(DO NOT INTERPRETE "0" VALUE)
{
digitalWrite(6, LOW);
digitalWrite(5, LOW);
}
if (af <= 3 && ab <= 3) //FOR ZEROING AS PROGRAM DO NOT ZERO BY DEFAULT (DO NOT INTERPRETE "0" VALUE)
{
digitalWrite(10, LOW);
digitalWrite(11, LOW);
}
} ////////////////////////END OF CAR MODE PWM GENERATION
else//////////////////////PWM GENERATION IF IN BOAT MODE
{
if (af > 3) //A FORWARD PWM&LOW
{
if (deepdischargealarmactivation == false) //if deep battery discharege alarm is not activated
{
analogWrite(5, af);
digitalWrite(6, LOW);
}
else //if deep battery discharege alarm is activated
{
analogWrite(5, (af / 3)); //speed reduced by 33%
digitalWrite(6, LOW);
}
}
if (ab > 3) //A BACKWARD PWM&LOW
{
if (deepdischargealarmactivation == false) //if deep battery discharege alarm is not activated
{
digitalWrite(5, LOW);
analogWrite(6, ab);
}
else //if deep battery discharege alarm is activated
{
digitalWrite(5, LOW);
analogWrite(6, (ab / 3)); //speed reduced by 33%
}
}
if (bf > 3) //B FORWARD PWM&LOW
{
servoangle = map(bf, 3, 255, neutral, (neutral - 55));
myservo.write(servoangle);
}
if (bb > 3) //B BACKWARD ENGINE PWM&LOW
{
servoangle = map(bb, 3, 255, neutral, (neutral + 55));
myservo.write(servoangle);
}
if (af <= 3 && ab <= 3) //FOR ZEROING AS PROGRAM DO NOT ZERO BY DEFAULT (DO NOT INTERPRETE "0" VALUE)
{
digitalWrite(5, LOW);
digitalWrite(6, LOW);
}
if (bf <= 3 && bb <= 3) //FOR NEUTRAL POSITIONAS PROGRAM DO NOT ZERO BY DEFAULT(DO NOT INTERPRETE "0" VALUE)
{
myservo.write(neutral);
}
} ////////////////////////END OF BOAT MODE PWM GENERATION
// FOR DEBUG ONLY. USING INTERRUPTS RECEIVED SIGNAL & OPERATION
// Serial.print("AF: ");
// Serial.println(af);
// Serial.print("AB: ");
// Serial.println(ab);
// Serial.print("BF: ");
// Serial.println(bf);
// Serial.print("BB: ");
// Serial.println(bb);
// FOR DEBUG ONLY. USING INTERRUPTS RECEIVED SIGNAL & OPERATION
} /////////////////////////////////////////////////Process Message End
void lighton()
{
strip.setBrightness(brightness);
strip.setPixelColor(0, strip.Color(255, 255, 255));
strip.setPixelColor(1, strip.Color(255, 255, 255));
strip.setPixelColor(2, strip.Color(255, 0, 0));
strip.show();
}
void lightoff()
{
strip.setBrightness(0);
strip.show();
}
void startsequence() //LED BLINK AT START
{
digitalWrite(13, HIGH); //BUILT IN LED ON
strip.setPixelColor(0, strip.Color(255, 255, 255));
strip.setPixelColor(1, strip.Color(255, 255, 255));
strip.setPixelColor(2, strip.Color(255, 0, 0));
strip.show();
delay(50);
digitalWrite(13, LOW); //BUILT IN LED OFF
strip.setBrightness(0);
strip.show();
delay(50);
digitalWrite(13, HIGH); //BUILT IN LED ON
strip.setBrightness(255);
strip.setPixelColor(0, strip.Color(255, 255, 255));
strip.setPixelColor(1, strip.Color(255, 255, 255));
strip.setPixelColor(2, strip.Color(255, 0, 0));
strip.show();
delay(50);
digitalWrite(13, LOW); //BUILT IN LED OFF
strip.setBrightness(0);
strip.show();
}
void servostart() //SEQUENCE OF SERVO MOVEMENTS AT START
{
myservo.write(neutral + 55); // sets the servo position according to the scaled value
delay(200);
myservo.write(neutral - 55); // sets the servo position according to the scaled value
delay(200);
myservo.write(neutral); // sets the servo position according to the scaled value
delay(100);
}
void testbeep()
{
digitalWrite(A5, HIGH);
delay(50);
digitalWrite(A5, LOW);
delay(50);
digitalWrite(A5, HIGH);
delay(50);
digitalWrite(A5, LOW);
delay(50);
digitalWrite(A5, HIGH);
delay(50);
digitalWrite(A5, LOW);
}
boolean modecheck() //voltage check at boot to detect whether it is a boat or not
{
for (byte i = 0; i < 5; i++)
{
bootval = analogRead(A0);
if (bootval > 600 && bootval < 700) //A0 value at USB approx. 659. 655, 665, at boat different
{
modecount = modecount + 1;
}
delay(100);
}
if (modecount == 5)
{
boatmode = true;
Serial.println("BOAT MODE !");
return boatmode;
}
else
{
Serial.println("CAR MODE !");
}
}// END OF MODE CHECK
//void writeIntIntoEEPROM(int lowestbatvoltage)
//{
// EEPROM.update(0, lowestbatvoltage >> 8); //address, variable. Shift by 8n bite, meaning saving only firts 8 bits from the digit in the first (out of two) bytes
// EEPROM.update(0 + 1, lowestbatvoltage & 0xFF); //For the second byte, we make an AND operation with 0xFF, which is the hexadecimal representation of 255 (you could write “& 255” instead of “& 0xFF”). This way, we only get the 8 bits on the right.
//}
//
//int readIntFromEEPROM()
//{
// return lowestbatEEPROM = (EEPROM.read(0) << 8) + EEPROM.read(0 + 1);
//}
//void sendping()
//{
// mySerial.print("XXXXX");
// Serial.println("!"); //////////////////////////////// PING SENT
//}
Kommentare
Kommentar hinzufügenVielen Dank für die Präsentation. Projekte rund um RC-Modelle gab es schon lange nicht mehr. Gib mir mal Packstation an und ich schicke dir ein kleines Geschenk! [Mehr erfahren]
Einer der Geschäfte schrieb: „Übertragungsreichweite: von 1 m bis 1000 m (weniger als 1 Meter, es funktioniert möglicherweise nicht richtig)“, im Ernst, können damit bis zu 1000 Meter erreicht werden... [Mehr erfahren]
Ich habe es nicht ausprobiert – vielleicht ist es mit der niedrigsten Bitrate und der Verwendung von Richtantennen möglich. Ich war positiv überrascht, als sich herausstellte, dass er die 200 m schafft... [Mehr erfahren]
Ich habe noch nichts von HC-12-Modulen gehört, vielleicht probiere ich es eines Tages mal aus. Schön, dass das RC-Projekt erschienen ist. [Mehr erfahren]
@frogqmak, hast du über den Einsatz von LoRa-Modulen nachgedacht? Oder z. B. nRF24L01? Ich hatte ein paar Sachen angesammelt und wollte etwas bauen. [Mehr erfahren]
Ich habe im Internet eine Anleitung für dieses Radio gefunden :) Ich habe es einmal mit NRF versucht, aber es gelang mir nicht, sie zum Laufen zu bringen, also landeten sie in der Box, und dann, nach ein... [Mehr erfahren]
So etwas wäre nützlich, um ein U-Boot in einer Tiefe von 2-3 m zu steuern. [Mehr erfahren]
@frogqmak, vielleicht ist es nicht dumm, aber mit dem Bearbeitungsstil hast du mir den Appetit aufs Frühstück verdorben. Entschuldigung. [Mehr erfahren]
@krzysztofkamienski, ich weiß, dass es drinnen nicht so toll ist, ;) aber übermäßiges Verwöhnen gibt mir keine Befriedigung, ich entwickle lieber das Programm oder neue Modelle und habe Spaß damit, als... [Mehr erfahren]
Was ist die Höchstgeschwindigkeit? [Mehr erfahren]
Ein Boot (Feilun FT009) angeblich 30 km/h, ein großes Auto (Revell Aqua Crawler) angeblich 20 km/h :) Ich werde das Boot nur im Freien testen, aber es hat einen speziellen Motor mit Wasserkühlung, der... [Mehr erfahren]
Hallo Ich kenne die Module nicht und habe mich nicht allzu sehr mit dem Code befasst, aber die im Programm verwendete Sendemethode könnte (hat?) einen großen Nachteil haben – den hohen Overhead des si4463-Protokolls.... [Mehr erfahren]
Hallo, vielen Dank für die wertvolle Bemerkung. Bei einem großen Modell (das beispielsweise aufgrund seines Gewichts eine Gefahr darstellen könnte) oder anderen Anwendungen, bei denen es auf Zuverlässigkeit... [Mehr erfahren]
Hallo, Ich füge aktualisierte (verbesserte) Versionen der Software für Sender und Empfänger hinzu. Wichtigste Änderungen: 1. Ich habe Unterstützung für Modellmotorsteuerungen (ESC) hinzugefügt,... [Mehr erfahren]
Es ist schwer, von Optimierung zu sprechen, bis du viele Verzögerungen aus dem Code, insbesondere dem Empfänger, eliminiert hast. Mach diese Übung und sende jedes Mal einen inkrementierten Zähler der gesendeten... [Mehr erfahren]
Vielen Dank für dein Kommentar. Der Code könnte zwar noch weiter optimiert werden, es wären jedoch erhebliche Änderungen erforderlich. Bisher funktioniert es einwandfrei, die Reichweite ist mehr als ausreichend,... [Mehr erfahren]
Hallo, ich füge eine weitere Revision des Empfängercodes hinzu. Zusätzlich zu kleineren Verbesserungen gibt es zwei wesentliche Änderungen. 1. Da das Boot SEHR manövrierfähig ist, d. h. bei hoher... [Mehr erfahren]