Hi guys. I am new in this field, can anyone help me and describe more precisely how to get the properties of my vtx (power supply channel frequency etc.) through arduino nano, and how can i send some messages to the arduino to change the parameters on the vtx if necessary?
yeah i knew i can send some messages trough serial port monitor but dont knew where to find commands for and i have some issues with lib that i downloaded...
I tried to use VTXcontrol (Pulse · RandyReover/VTXControl · GitHub), but don't quite understand how to make it work with my vtx. I use it for halfduplex smartaudio and got some errors (in file VTXtest.ino they included to check if something don't work properly) VTXError isNotListening, vtxPortBufferEmpty,
TxDelayZero, RxStopBitNotSet.
my vtx is akk alpha10
my board is nano v3
I seek for your guidance/help, by the way, sorry have problem navigating the forum.
UPD: i tried hard to code my own but stuck for some reason my arduino and vtx cant "comunicate" maybe some reason is issues with code or smart audio comands that i trying to send?
UPD1: For some reason I have a problem in SmartAudio.h because it sends commands like 9 A B C etc but 9 is 4 characters in 0x09, A character in 0xAA... I think it's a problem with how I form the command, can anyone help me solve the problem?
main.ino
```cpp
#include <SoftwareSerial.h> // Include the library for working with software serial port
#include "SmartAudio.h" // Include the header file of the SmartAudio library
// Create an object for connecting SmartAudio via the serial port
// We use the same pin (13) for RX and TX since half-duplex mode is used
SoftwareSerial mySerial(13, 13); // RX and TX use the same pin (13) for half-duplex
// Initialize the SmartAudio object using our software serial port
SmartAudio vtx(mySerial);
void setup() {
// Set up the main port for outputting messages to the serial monitor
Serial.begin(9600); // Set the baud rate for the main port to 9600 baud (bits per second)
// Set up the port for interacting with SmartAudio
mySerial.begin(9600); // Set the baud rate for SmartAudio to 9600 baud
// Initialize SmartAudio to start working with VTX
vtx.begin(); // Start and configure the SmartAudio object
// Debug message confirming that SmartAudio has been successfully initialized
Serial.println("SmartAudio initialized.");
}
void loop() {
// The main loop of the program that runs continuously
//uint16_t settings = vtx.getSettings();
// Retrieve the frequency from the VTX
uint16_t frequency = vtx.getFrequency(); // Get the frequency set on the VTX
// Check if the frequency is within the acceptable range
if (frequency >= 4990 && frequency <= 5945) { // Frequency range for AKK Alpha 10 is from 4990 MHz to 5945 MHz
Serial.print("Frequency: "); // Message to display the frequency
Serial.print(frequency); // Output the frequency
Serial.println(" MHz"); // Add the unit of measurement (MHz)
} else {
Serial.println("Error retrieving frequency or frequency out of acceptable range."); // Error message if the frequency is out of range
}
// Retrieve the channel from the VTX
uint8_t channel = vtx.getChannel(); // Get the channel number set on the VTX
// Check if the channel is within the acceptable range
if (channel >= 1 && channel <= 80) { // Channel range for AKK Alpha 10 is from 1 to 80
Serial.print("Channel: "); // Message to display the channel number
Serial.println(channel); // Output the channel number
} else {
Serial.println("Error retrieving channel or channel out of acceptable range."); // Error message if the channel number is out of range
}
// Retrieve the band from the VTX
uint8_t band = vtx.getBand(); // Get the band set on the VTX
// Check if the band is within the acceptable range
if (band >= 1 && band <= 5) { // Band values for AKK Alpha 10 range from 1 to 5
Serial.print("Band: "); // Message to display the band
Serial.println(band); // Output the band
} else {
Serial.println("Error retrieving band or band out of acceptable range."); // Error message if the band value is out of range
}
// Retrieve the voltage from the VTX
uint16_t voltage = vtx.getVoltage(); // Get the voltage set on the VTX
// Check if the voltage is within the acceptable range
if (voltage >= 7000 && voltage <= 24000) { // Acceptable voltage range from 7V (7000 mV) to 24V (24000 mV)
Serial.print("Voltage: "); // Message to display the voltage
Serial.print(voltage); // Output the voltage
Serial.println(" mV"); // Add the unit of measurement (mV)
} else {
Serial.println("Error retrieving voltage or voltage out of acceptable range."); // Error message if the voltage is out of range
}
// Retrieve the PitMode status from the VTX
uint16_t pitmode = vtx.getPitmode(); // Get the PitMode status set on the VTX
// Check if the PitMode is within the acceptable range
if (pitmode == 0 || pitmode == 1) { // Possible PitMode values for AKK Alpha 10: 0 (off) or 1 (on)
Serial.print("Pitmode: "); // Message to display the PitMode status
Serial.print(pitmode); // Output the PitMode value
Serial.println(" (0 = Off, 1 = On)"); // Add an explanation that 0 means off and 1 means on
} else {
Serial.println("Error retrieving pitmode or pitmode out of acceptable range."); // Error message if the PitMode value is out of range
}
// Delay before the next data retrieval cycle
delay(5000); // Delay of 5 seconds to avoid requesting data too frequently
}
SmartAudio.h
#ifndef SMARTAUDIO_H_
#define SMARTAUDIO_H_
#include <Stream.h> // Include the Stream class, which is used for working with serial ports
// Configuration for working with SmartAudio
#define SMARTAUDIO_IGNORE_CRC true // Ignore CRC (Cyclic Redundancy Check) validation
#define SMARTAUDIO_WRITE_ZEROBYTES_AT_THE_END true // Add a zero byte at the end of the sent command
#define SMARTAUDIO_BUFFER_CAPACITY 5 // Buffer capacity for receiving data
// SmartAudio serial port configuration
#define AP_SMARTAUDIO_UART_CFG 802 // UART configuration (custom setting)
#define AP_SMARTAUDIO_UART_BAUD 9600 // Baud rate 9600
#define AP_SMARTAUDIO_SMARTBAUD_MIN 9600 // Minimum baud rate
#define AP_SMARTAUDIO_SMARTBAUD_ARDU 4900 // Special baud rate for Arduino
#define AP_SMARTAUDIO_SMARTBAUD_MAX 5040 // Maximum baud rate
#define AP_SMARTAUDIO_SMARTBAUD_STEP 60 // Baud rate step increment
#define AP_SMARTAUDIO_UART_BUFSIZE_RX 16 // Buffer size for receiving data
#define AP_SMARTAUDIO_UART_BUFSIZE_TX 16 // Buffer size for transmitting data
#define AP_SMARTAUDIO_MAX_PACKET_SIZE 32 // Maximum packet size
// SmartAudio commands (defined according to specification)
#define SMARTAUDIO_CMD_GET_SETTINGS 0xAA 0x01 0x00 0x01
#define SMARTAUDIO_CMD_GET_FREQUENCY 0x09 // Command to get frequency
#define SMARTAUDIO_CMD_GET_CHANNEL 0x07 // Command to get channel
#define SMARTAUDIO_CMD_GET_BAND 0x0A // Command to get band
#define SMARTAUDIO_CMD_GET_VOLTAGE 0x0B // Command to get voltage
#define SMARTAUDIO_CMD_GET_PITMODE 0x0C // Command to get pitmode status
// Command frame sizes
#define SMARTAUDIO_COMMAND_FRAME_SIZE 5 // Frame size for a command (without data)
#define SMARTAUDIO_U8_COMMAND_FRAME_SIZE 6 // Frame size for a command with one byte of data
#define SMARTAUDIO_U16_COMMAND_FRAME_SIZE 7 // Frame size for a command with two bytes of data
// Structure for the frame header
struct FrameHeader {
uint8_t syncByte; // Synchronization byte (start of frame)
uint8_t headerByte; // Header byte (frame identifier)
uint8_t command; // Command code
uint8_t length; // Data length (payload)
// Method to initialize the frame header
void init(uint8_t cmd, uint8_t payloadLength) {
syncByte = 0xAA; // Set the synchronization byte
headerByte = 0x55; // Set the header byte
length = payloadLength; // Set the data length
command = cmd; // Set the command
}
} __attribute__((packed)); // Pack the structure without alignment
// Structure for the data frame
struct Frame {
FrameHeader header; // Frame header
uint8_t payload[3]; // Data (up to 3 bytes)
} __attribute__((packed)); // Pack the structure without alignment
// Function to calculate CRC8 (Cyclic Redundancy Check)
static uint8_t sa_CRC8(const void* data, uint32_t length) {
uint8_t crc = 0; // Initialize CRC to zero
const uint8_t* p = (const uint8_t*)data; // Pointer to the data
const uint8_t* pend = p + length; // Pointer to the end of the data
// Loop through each byte of data
for (; p != pend; p++) {
crc ^= *p; // Perform XOR with the current byte of data
// Compute the CRC using the algorithm
for (uint8_t i = 0; i < 8; ++i) {
if (crc & 0x80) {
crc = (crc << 1) ^ 0xd5; // Apply the CRC polynomial
} else {
crc = crc << 1; // Shift left
}
}
}
return crc; // Return the CRC result
}
class SmartAudio {
public:
SmartAudio(Stream& serial); // Constructor, takes a reference to a Stream object
void begin(); // Initialization method
void sendCommand(uint8_t command, uint8_t* payload, uint8_t length); // Send a command
uint8_t receiveResponse(uint8_t* buffer, uint8_t length); // Receive a response
uint16_t getFrequency(); // Get the frequency
uint8_t getChannel(); // Get the channel
uint8_t getBand(); // Get the band
uint16_t getSettings();
uint16_t getVoltage(); // Get the voltage
uint16_t getPitmode(); // Get the pitmode status
private:
Stream& _serial; // Reference to a Stream object (e.g., Serial)
};
#endif // SMARTAUDIO_H_
SmartAudio.cpp
#include "SmartAudio.h" // Include the SmartAudio header file
#include <Arduino.h> // Include the Arduino header file for millis() function
// Constructor for the SmartAudio class. Initializes the internal _serial variable.
SmartAudio::SmartAudio(Stream& serial) : _serial(serial) {
// Initialization of the internal Serial stream passed to the constructor.
}
// Initialization method. Executed at program startup.
void SmartAudio::begin() {
// If additional initialization is needed, add it here
}
// Method for sending a SmartAudio command
void SmartAudio::sendCommand(uint8_t command, uint8_t* payload, uint8_t length) {
Serial.print("Sending command: "); // Debug message
Serial.println(command, HEX); // Display the command in hexadecimal format
_serial.write(0xAA); // Send synchronization byte
_serial.write(0x55); // Send header byte
_serial.write(command); // Send the command
_serial.write(length); // Send the data length
if (payload && length > 0) {
_serial.write(payload, length); // Send the data if available
}
if (SMARTAUDIO_WRITE_ZEROBYTES_AT_THE_END) {
_serial.write((uint8_t)0); // Send a zero byte if specified
}
}
// Method for receiving a response from the device
uint8_t SmartAudio::receiveResponse(uint8_t* buffer, uint8_t length) {
Serial.println("Waiting for response..."); // Debug message
unsigned long startTime = millis(); // Record the current time
uint8_t received = 0; // Number of bytes received
// Loop to wait for data (maximum 5 seconds)
while (millis() - startTime < 5000) {
if (_serial.available()) { // Check if data is available
buffer[received++] = _serial.read(); // Read data and store it in the buffer
Serial.print("Bytes received: ");
Serial.println(buffer[received - 1], HEX); // Debug message for received byte
if (received >= length) break; // Exit loop if enough data is received
}
}
if (received < length) {
Serial.println("Failed to receive enough data."); // Debug message
return 0; // Return 0 in case of error
}
// Check CRC if not ignored
if (!SMARTAUDIO_IGNORE_CRC) {
uint8_t crc = sa_CRC8(buffer, length); // Calculate CRC
Serial.print("Expected CRC: ");
Serial.println(crc, HEX); // Display the expected CRC
uint8_t receivedCRC = _serial.read(); // Read the received CRC
if (crc != receivedCRC) {
Serial.println("CRC error."); // Display CRC error if mismatch
return 0; // Return 0 in case of error
}
}
return received; // Return the number of bytes received
}
// Method for getting the transmitter frequency
uint16_t SmartAudio::getFrequency() {
sendCommand(SMARTAUDIO_CMD_GET_FREQUENCY, nullptr, 0); // Send the command to get the frequency
uint8_t buffer[2]; // Buffer to store the response
if (receiveResponse(buffer, 2) == 2) { // If 2 bytes of data are received
return (buffer[0] << 8) | buffer[1]; // Convert two bytes into a 16-bit value
}
Serial.println("Failed to get frequency."); // Display error if data is not received
return 0; // Return 0 in case of error
}
// Method for getting the current channel
uint8_t SmartAudio::getChannel() {
sendCommand(SMARTAUDIO_CMD_GET_CHANNEL, nullptr, 0); // Send the command to get the channel
uint8_t buffer[1]; // Buffer to store the response
if (receiveResponse(buffer, 1) == 1) { // If 1 byte of data is received
return buffer[0]; // Return the channel value
}
Serial.println("Failed to get channel."); // Display error if data is not received
return 0; // Return 0 in case of error
}
// Method for getting the current band
uint8_t SmartAudio::getBand() {
sendCommand(SMARTAUDIO_CMD_GET_BAND, nullptr, 0); // Send the command to get the band
uint8_t buffer[1]; // Buffer to store the response
if (receiveResponse(buffer, 1) == 1) { // If 1 byte of data is received
return buffer[0]; // Return the band value
}
Serial.println("Failed to get band."); // Display error if data is not received
return 0; // Return 0 in case of error
}
// Method for getting the current voltage
uint16_t SmartAudio::getVoltage() {
sendCommand(SMARTAUDIO_CMD_GET_VOLTAGE, nullptr, 0); // Send the command to get the voltage
uint8_t buffer[2]; // Buffer to store the response
if (receiveResponse(buffer, 2) == 2) { // If 2 bytes of data are received
return (buffer[0] << 8) | buffer[1]; // Convert two bytes into a 16-bit value
}
Serial.println("Failed to get voltage."); // Display error if data is not received
return 0; // Return 0 in case of error
}
// Method for getting the pitmode status (low-power mode)
uint16_t SmartAudio::getPitmode() {
sendCommand(SMARTAUDIO_CMD_GET_PITMODE, nullptr, 0); // Send the command to get pitmode
uint8_t buffer[2]; // Buffer to store the response
if (receiveResponse(buffer, 2) == 2) { // If 2 bytes of data are received
return (buffer[0] << 8) | buffer[1]; // Convert two bytes into a 16-bit value
}
Serial.println("Failed to get pitmode."); // Display error if data is not received
return 0; // Return 0 in case of error
}