APC220 radio
Pinout:
For configuration you need to access TX and RX,
See below for more code and examples
In the bottom an example how to reprogram apc200 insitu on AAU cansat shield v8.
The simple library
Just a headerfile:
(click for apc220cfg.h code)
/**
* (C) 2021
*
* Jens Dalsgaard Nielsen <jdn@es.aau.dk>
* http://es.aau.dk/staff/jdn
* http://jensd.dk
* Section of Automation & Control
* Aalborg University,
* Denmark
*
* "THE BEER-WARE LICENSE" (frit efter PHK)
* <jdn@es.aau.dk> wrote this file. As long as you
* retain this notice you can do whatever you want
* with this stuff, but You shall add your
* name and email and date for your
* modification.
*
* If we meet some day, and you think
* this stuff is worth it ...
* you can buy me a beer in return :-)
* or if you are real happy then ...
* single malt will be well received :-)
*
* Use it at your own risk - no warranty
*
**/
#ifndef _APC220CFG_H
#define _APC220CFG_H
#include <SoftwareSerial.h>
class apc220cfg {
public:
apc220cfg(SoftwareSerial *s, int setPin)
{
_setPin = setPin;
sps = s;
fl = 1; // indicate its sw serial
pinMode(_setPin, OUTPUT);
};
apc220cfg(HardwareSerial *s, int setPin)
{
_setPin = setPin;
sph = s;
fl = 0; // indicate its hw serial
// begin(9600);
pinMode(_setPin, OUTPUT);
};
int rdCfg(char *reply)
{
char rd;
int cnt = 0;
apc220ToSetMode();
if (fl) {
sps->write("RD\r\n");
delay(200 + 30); // 200 datasheet - 30 then all chars has arrived
while (sps->available()) {
rd = (char) sps->read();
*(reply+cnt) = rd;
cnt++;
}
}
else {
sph->write("RD\r\n");
delay(200 + 30); // 200 datasheet - 30 then all chars has arrived
while (sph->available()) {
rd = (char) sph->read();
*(reply+cnt) = rd;
cnt++;
}
}
apc220ToNormalMode();
// reply format
// PARA xxxxxx x x x x\r\n" == 21
// 1234567890123456789 0 1 == 21
*(reply+cnt-2) = 0x00; // terminate string remove \r\n
// check if reply i valid - not 100% safe but ok I think
if ( (cnt == 21)
&& (reply[0] == 'P')
&& (reply[1] == 'A')
&& (reply[2] == 'R')
&& (reply[3] == 'A')
){
return 0;
}
else {
reply[0] = 'E';
reply[1] = reply[2] = 'R';
reply[3] = 0x00;
return -1;
}
}
void wrCfg(const char *cmd)
{
char rd;
// we get 412000 3 9 3 0
// 01234567890123
apc220ToSetMode();
if (fl) {
sps->write("WR ");
sps->write(cmd);
sps->write("\r\n"); // expected from apc220
delay(200 + 35); // 200 datasheet - add 35 so all chars has arrived
while (sps->available()) {
rd = (char) sps->read(); // clear reply
}
}
else {
sph->write("WR ");
sph->write(cmd);
sph->write("\r\n"); // expected from apc220
delay(200 + 35); // 200 datasheet - add 35 so all chars has arrived
while (sph->available()) {
rd = (char) sph->read(); // clear reply
}
}
apc220ToNormalMode();
}
private:
void apc220ToSetMode(void)
{
digitalWrite(_setPin, LOW);
delay(10); // 2acc datasheet (1msec)
};
void apc220ToNormalMode()
{
delay(10);
digitalWrite(_setPin, HIGH);
delay(2); // acc datasheet (1msec)
};
protected:
HardwareSerial *sph;
SoftwareSerial *sps;
int fl;
int _setPin;
};
#endif /* not defined _APC220CONFIG_H */
/*
* Some specs for apc220
*
* - Frequency: 415MHz to 455MHz (1kHz step +-100Hz)
* - GFSK modulation
* - Channel spacing 200KHz(at least JDN)
* - Max Output power: 20mW (10 level adjustable)
* - Sensitivity: -117dB@1200bps
* - Air data rate: 1200 to 19200bps.
* - UART baud rate: 1200 to 19200bps.
* - Serial parity: 8E1\/8N1\/8O1
* - Data buffer: 512bytes
* - Humidity: 10%~90%
* - Temperature: -30℃ - 85℃
* - Supply voltage: 3.4 – 5.5V (the ripple is ±50mV )
* - Transmit current: 35mA
* - Receiving current:32mA
* - Sleeping current: 5uA
* - RF line-in-sight range:1000m (2400 baud)
*
*/
click for raw headerfile code
apc220cfg.zip can be installed in you Arduino environment
Configuration parameters
See in datasheet for how to configure the radio
It consists of a simple textstring with the following format:
config string: example: FFFFFF R P B C
FFFFFF - Frequency
434000 is 434,000 MHz
R: radio link baudrate in kHz
1/2/3/4 equals 2400(1km)/4800/9600/19200bps
P: Radio output power
0 .. 9 where 9(highest) equals 13dBm(20mW)
B UART baudrate (between radio and you
UART baudrate - 0/1/2/3/4/5/6 equals 1200/2400/4800/9600/19200/38400/57600bps
C: UART parity check
Byte Check Parity - 0/1/2 equals NoCheck(8N1)/EvenParity(8E1)/OddParity(8O1)
config string: example:
415000 MHz 9600 baud-in-air full radiopower uart baudrate 57600 no parity
gives
415000 3 9 6 0
APC220 radio - my code
First two strip down example
Simple config code
The radio is connected to the UNO serial port.
The set pin is connected to D8
Power and ground on radio from somewhere else.
(click for apc220 cfg simple hardware serial code)
#include "apc220cfg.h"
// just an easy interface to configure an apc220 on the port
apc220cfg serialcfg(&Serial, 8); // pin 8 here for set pin on radio
// assume enable pin has no conenction so radio will be on
// --------------------------^-- dig pin to force apc in prog mode
//--------------------^--------- reference to serial port
char x[34];
void setup() {
int res;
// put your setup code here, to run once:
Serial.begin(9600); // initalise direct
delay(500); // to stabilize radio - too much time but ...
serialcfg.wrCfg("412000 2 9 3 0");
res = serialcfg.rdCfg(x);
if (res == 0)
{
// config read from radio seems ok
}
else {
// seems bad bad
}
}
void loop() {}
raw file
Simple config code software radio
(click for apc220 cfg simple software serial code)
#include "apc220cfg.h"
SoftwareSerial soft01(10, 11); // RX, TX
// just an easy interface to configure an apc220 on the port
apc220cfg soft01cfg(&soft01, 8);
// --------------------------^-- dig pin to force apc in prog mode
//--------------------^--------- reference to serial port
char x[34];
void setapc220pin8to13(const char cfg[])
{
// we need to give radio power and enable by dig pins 12 and 13
pinMode(13, OUTPUT);
digitalWrite(13, HIGH); // power on
pinMode(12, OUTPUT);
digitalWrite(12, HIGH); // enable radio
delay(500); // to stabilize radio - too much time but ...
soft01cfg.wrCfg(cfg); //
// show new config
if (0 == soft01cfg.rdCfg(x)) {
// we did read a config
Serial.print("yes: ");
Serial.println(x);
}
else {
Serial.println("hmm");
// nope
}
}
void setup() {
int res;
// put your setup code here, to run once:
Serial.begin(9600); // initalise direct
soft01.begin(9600); // initalise direct
// SOFTSERIAL
setapc220pin8to13("412000 2 9 3 0");
}
// or just very simple
//void setup() {
// int res;
// // put your setup code here, to run once:
// Serial.begin(9600); // initalise direct
// soft01.begin(9600); // initalise direct
//
// // we need to give radio power and enable by dig pins 12 and 13
// pinMode(13, OUTPUT);
// digitalWrite(13, HIGH); // power on
//
// pinMode(12, OUTPUT);
// digitalWrite(12, HIGH); // enable radio
//
// delay(500); // to stabilize radio - too much time but ...
// soft01cfg.wrCfg("412000 2 9 3 0"); //
//
//}
void loop() {}
raw file
More examples with more printout
Just below headerfile code and in bottom an example
happy hacking
apc220 config
Too much code but on other hand lot of info
The APC220 is connected to D8-D13. If your radio has pin just …
Serial.println(F(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "));
Serial.println(F("Attach radio directly to Arduino on pin 8 to gnd as shown below"));
Serial.println(F("or solder some wires so you can connect the radio on the shields"));
Serial.println(F("to 8,10,11,13 and 14. Remove any jumpers on shield "));
Serial.println(F(" "));
Serial.println(F(" ---------------"));
Serial.println(F(" | A aref"));
Serial.println(F(" | R GND-++-GND---------------"));
Serial.println(F(" | D 13 ++ 5V |=======antenna =======>"));
Serial.println(F(" | U 12 -- ENABLE(high) |"));
Serial.println(F(" | I 11 ++ RX |"));
Serial.println(F(" | N 10 ++ TX |"));
Serial.println(F(" 5V O 09 -- not used |"));
Serial.println(F(" GND 08-++ SET/CONFIG(low)--|"));
Serial.println(F(" ---------------"));
Serial.println(F(" | ~ 07"));
Serial.println(F(" | ~ 06"));
Serial.println(F(" | ~ 05"));
Serial.println(F(" | 04"));
Serial.println(F(" | ~ 03"));
Serial.println(F(" | 02"));
Serial.println(F(" | TX 01"));
Serial.println(F(" | RX 00"));
Serial.println(F(" ---------------"));
Serial.println(F("Remember to connect5V(pin13) to 5V as p13 might no be able"));
Serial.println(F("to give enough power for normal op"));
(click for apc220cfgexample code)
#include "apc220cfg.h"
// just whoing how to embed embedded reprogram of apc220 in your program
// There is a hardware serial port and software serial version
//
// we need to create a software serial port
// we dont need to do it for the hardware serial ports
// bq they are already created in the runtime systems
// MORE COMMENTS IN BOTTOM OF FILE
//
SoftwareSerial soft01(10, 11);
// just an easy interface to configure an apc220 on the port
apc220cfg soft01cfg(&soft01, 8);
apc220cfg serialcfg(&Serial, 5);
// --------------------------^-- dig pin to force apc in prog mode
//--------------------^--------- reference to serial port
void drawRadio8to13();
char x[34];
char newx[]="412000 2 9 3 0";
void setup() {
int res;
// put your setup code here, to run once:
Serial.begin(9600); // initalise
soft01.begin(9600); // initalise
// SOFTSERIAL
//drawRadio8to13(); // just to show a "picture" of setup
// SW config on pin 8 to 13
// pin 13 i power
// pin 12 is enable radio
pinMode(13, OUTPUT);
digitalWrite(13, HIGH); // power on
pinMode(12, OUTPUT);
digitalWrite(12, HIGH); // enable radio
delay(300), // just to stabilize radio - way to long but ...
// read present config
res = soft01cfg.rdCfg(x); // returns 0 if ok, otherwise -1
if (res == 0) {
Serial.println(x);
}
else {
Serial.print("no radio found");
Serial.println(res);
}
// push new config
serialcfg.wrCfg("412000 2 9 3 0");
//or serialcfg.wrCfg(newx);
// on serial port use serial.wrCfg etc
// NB remember to have setup pin on radio connected to a dig pin
}
void loop() {}
void drawRadio8to13()
{
Serial.println(F(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "));
Serial.println(F("Attach radio directly to Arduino on pin 8 to gnd as shown below"));
Serial.println(F("or solder some wires so you can connect the radio on the shields"));
Serial.println(F("to 8,10,11,13 and 14. Remove any jumpers on shield "));
Serial.println(F(" "));
Serial.println(F(" ---------------"));
Serial.println(F(" | A aref"));
Serial.println(F(" | R GND-++-GND---------------"));
Serial.println(F(" | D 13 ++ 5V |=======antenna =======>"));
Serial.println(F(" | U 12 -- ENABLE(high) |"));
Serial.println(F(" | I 11 ++ RX |"));
Serial.println(F(" | N 10 ++ TX |"));
Serial.println(F(" 5V O 09 -- not used |"));
Serial.println(F(" GND 08-++ SET/CONFIG(low)--|"));
Serial.println(F(" ---------------"));
Serial.println(F(" | ~ 07"));
Serial.println(F(" | ~ 06"));
Serial.println(F(" | ~ 05"));
Serial.println(F(" | 04"));
Serial.println(F(" | ~ 03"));
Serial.println(F(" | 02"));
Serial.println(F(" | TX 01"));
Serial.println(F(" | RX 00"));
Serial.println(F(" ---------------"));
Serial.println(F("Remember to connect5V(pin13) to 5V as p13 cant give enough power"));
}
raw file
apc220
On an Uno locate your apc220 on pin d 8-14 and configure your radio
(click for apc220cfg on pin8 to 13 code)
#include "apc220cfg.h"
// just whoing how to embed embedded reprogram of apc220 in your program
// There is a hardware serial port and software serial version
//
// we need to create a software serial port
// we dont need to do it for the hardware serial ports
// bq they are already created in the runtime systems
// MORE COMMENTS IN BOTTOM OF FILE
//
SoftwareSerial soft01(10, 11);
// just an easy interface to configure an apc220 on the port
apc220cfg soft01cfg(&soft01, 8);
apc220cfg serialcfg(&Serial, 5);
// --------------------------^-- dig pin to force apc in prog mode
//--------------------^--------- reference to serial port
char x[34];
void drawRadio8to13()
{
Serial.println(F(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "));
Serial.println(F("Attach radio directly to Arduino on pin 8 to gnd as shown below"));
Serial.println(F("or solder some wires so you can connect the radio on the shields"));
Serial.println(F("to 8,10,11,13 and 14. Remove any jumpers on shield "));
Serial.println(F(" "));
Serial.println(F(" ---------------"));
Serial.println(F(" | A aref"));
Serial.println(F(" | R GND-++-GND---------------"));
Serial.println(F(" | D 13 ++ 5V |=======antenna =======>"));
Serial.println(F(" | U 12 -- ENABLE(high) |"));
Serial.println(F(" | I 11 ++ RX |"));
Serial.println(F(" | N 10 ++ TX |"));
Serial.println(F(" 5V O 09 -- not used |"));
Serial.println(F(" GND 08-++ SET/CONFIG(low)--|"));
Serial.println(F(" ---------------"));
Serial.println(F(" | ~ 07"));
Serial.println(F(" | ~ 06"));
Serial.println(F(" | ~ 05"));
Serial.println(F(" | 04"));
Serial.println(F(" | ~ 03"));
Serial.println(F(" | 02"));
Serial.println(F(" | TX 01"));
Serial.println(F(" | RX 00"));
Serial.println(F(" ---------------"));
Serial.println(F("Remember to connect5V(pin13) to 5V as p13 cant give enough power"));
}
void setupHlp()
{
Serial.println(F("\nHELP MENU"));
Serial.println(F(" w - write/program apc220"));
Serial.println(F(" write example: 434000 3 9 3 0 is..."));
Serial.println(F(" write example: FFFFFF R P B C"));
Serial.println(F(" 434,000 MHz 9600 baud in air, 20mW, 9600baud on UART, No Parity(8N1)"));
Serial.println(F(" FFFFFF: Radio frequency in kHz"));
Serial.println(F(" R: Rf data rate - 1/2/3/4 equals 2400(1km)/4800/9600/19200bps"));
Serial.println(F(" P: Radio output power - 0 .. 9 9 equals 13dBm(20mW)."));
Serial.println(F(" B: UART baudrate - 0/1/2/3/4/5/6 equals 1200/2400/4800/9600/19200/38400/57600bps"));
Serial.println(F(" C: Byte Chek Parity - 0/1/2 equals NoCheck(8N1)/EvenParity(8E1)/OddParity(8O1)"));
Serial.println(F(" Frequency 415MHz to 455MHz (1kHz step +-100Hz)"));
Serial.println(F(" Channel spacing 200KHz(at least /JDN))"));
Serial.println(F(" NB the apc220 has broader frequency band than the allowd ISM band:"));
Serial.println(F(" "));
Serial.println(F(" r - read apc200 configuration"));
Serial.println(F(" p - print placement for apc220 on UNO"));
Serial.println(F(" h - this menu"));
}
void setapc220pin8to13()
{
int res;
// insert radio
Serial.println("bef start");
drawRadio8to13();
setupHlp();
// we need to give rtadio power and enable by dig pins 12 and 13
pinMode(13, OUTPUT);
digitalWrite(13, HIGH); // power on
pinMode(12, OUTPUT);
digitalWrite(12, HIGH); // enable radio
delay(500); // to stabilize radio - too much time but ...
// read, configure and read soft serial port
res = soft01cfg.rdCfg(x); // returns 0 if ok, otherwise -1
if (res == 0) {
Serial.println(x);
}
else {
Serial.print("no radio found");
Serial.println(res);
}
soft01cfg.wrCfg("412000 2 9 3 0"); // See manual for expl
// show new config
if (0 == soft01cfg.rdCfg(x)) {
Serial.println("rd2");
Serial.println(x);
}
else {
Serial.println(x);
Serial.println("no radio2");
}
}
void setapc220Serial()
{
int res;
// HW SERIAL
// use on radio on std serial port.
// a lite bit nasty bq
// you cant have radio and usb serial in parallel
// but you can configure radio
// and you can on cansat shield
// connect read connection to openlog til radio so you can see answers¨
// and look in the logfile on the sdcard
// or just compare what you get from the radio with
// the config strign and see if they are equal.
//Jen
delay(500);
Serial.println("bef start - hw serial: Serial");
delay(500); // to stabilize radio - too much time but ...
// read, configure and read soft serial port
res = serialcfg.rdCfg(x); // returns 0 if ok, otherwise -1
serialcfg.wrCfg("412000 2 9 3 0");
if (0 == serialcfg.rdCfg(x)) {
// ok
}
else {
//else
}
}
void setup() {
int res;
// put your setup code here, to run once:
Serial.begin(9600); // initalise direct
soft01.begin(9600); // initalise direct
// SOFTSERIAL
setapc220pin8to13();
// setapc220Serial();
}
void loop() {}
raw file
Simple and efficent version of previous example
Just the few lines to configure apc220 on dig pin 8 to 13
(click for apc220cfg pin8to13 simple code)
#include "apc220cfg.h"
SoftwareSerial soft01(10, 11); // RX, TX
// just an easy interface to configure an apc220 on the port
apc220cfg soft01cfg(&soft01, 8);
// --------------------------^-- dig pin to force apc in prog mode
//--------------------^--------- reference to serial port
char x[34];
void setapc220pin8to13(const char cfg[])
{
// we need to give radio power and enable by dig pins 12 and 13
pinMode(13, OUTPUT);
digitalWrite(13, HIGH); // power on
pinMode(12, OUTPUT);
digitalWrite(12, HIGH); // enable radio
delay(500); // to stabilize radio - too much time but ...
soft01cfg.wrCfg(cfg); //
// show new config
if (0 == soft01cfg.rdCfg(x)) {
// we did read a config
Serial.print("yes: ");
Serial.println(x);
}
else {
Serial.println("hmm");
// nope
}
}
void setup() {
int res;
// put your setup code here, to run once:
Serial.begin(9600); // initalise direct
soft01.begin(9600); // initalise direct
// SOFTSERIAL
setapc220pin8to13("412000 2 9 3 0");
}
// or just very simple
//void setup() {
// int res;
// // put your setup code here, to run once:
// Serial.begin(9600); // initalise direct
// soft01.begin(9600); // initalise direct
//
// // we need to give radio power and enable by dig pins 12 and 13
// pinMode(13, OUTPUT);
// digitalWrite(13, HIGH); // power on
//
// pinMode(12, OUTPUT);
// digitalWrite(12, HIGH); // enable radio
//
// delay(500); // to stabilize radio - too much time but ...
// soft01cfg.wrCfg("412000 2 9 3 0"); //
//
//}
void loop() {}
raw file
Reprogram by SW serial on AAU cansat shield v8
(click for code)
#include <apc220cfg.h>
SoftwareSerial softSer01(4,5); // RX, TX
//for config you need
apc220cfg soft01(&softSer01, 7);
char x[35];
int res;
void setup()
{
Serial.begin(115200);
softSer01.begin(9600);
delay(1000);
soft01.wrCfg("434000 3 9 3 0");
delay(100);
res = soft01.rdCfg(x);
if (res == 0) {
Serial.println(x);
}
else {
Serial.print("no radio found");
Serial.println(res);
}
}
void loop() {
// put your main code here, to run repeatedly:
}
raw file
A few APC220 specs
See here
|