Ebaystä löytyy muutamalla eurolla TI CC1101 pohjaisia SPI (ISM 433 MHz...) lähetin-vastaanottimia (2-FSK, 4-FSK, GFSK, MSK, ASK/OOK).
https://www.ebay.com/sch/i.html?_from=R40&_sacat=0&_nkw=arduino+cc1101&_sop=15
From ebay one can buy cheap TI CC1101 SPI transceiver modules (ISM 433 Mhz, FSK,GFSK,MSK,ASK) for the Arduino.
Datasheet: http://www.ti.com/lit/ds/symlink/cc1101.pdf
Netistä löytyy pari kirjastoa Arduinolle CC1101 ohjaukseen: https://github.com/veonik/arduino-cc1101
A few libs for Arduino to control CC1101 exists in the Internet, e.g. https://github.com/veonik/arduino-cc1101
Modasin ym. kirjastoa siten että void CC1101::setCCregs(void) metodissa kommentoin sendData(packet); lauseen.
I modified that lib by commenting out sendData(packet) in CC1101:setCCregs(void) method.
http://www.electrodragon.com/w/images/a/a7/Cc1101_2_bb.png
CC1101:n laittaminen RX tilaan onnistui lopulta kun resetoi Arduinon muutaman kerran/odotteli vähän aikaa. Jostain syystä piiri jää tuon tuostakin RX CALIBRATE tilaan ....
To set the CC1101 to RX state required many Arduino resets and wait some time after reset. CC1101 tends to leave in RX calibrate state ...
#include <Arduino.h>
#include <cc1101.h>
#include <ccpacket.h>
// Speed MDMCFG4 MDMCFG3
// 31.25 C0 43 PSK31
// 45.5 C0 D5 RTTY
// 63 C1 45 PSK63
// 441 C4 1D FSK441
//
// 75 C1 83
// 150 C2 83
// 300 C3 83
// 600 C4 83
// 1200 C5 83
// 2400 C6 83
// 4800 C7 83
// 9600 C8 83
// 19200 C9 83
// 38400 CA 83
// 76800 CB 83
// 153600 CC 83
// 307200 CD 83
//
// 1800 C6 22
// 3600 C7 22
// 7200 C8 22
// 14400 C9 22
// 28800 CA 22
// 57600 CB 22
// 115200 CC 22
// 230400 CD 22
#define SERIAL_SPEED 9600
#define CC1101_RX_DELAY 50
#define CC1101_VAL_FREQ2_433 0x10
#define CC1101_VAL_FREQ1_433 0xA7
#define CC1101_VAL_FREQ0_433 0x10
#define CC1101_VAL_FREQ2_423875 0x10
#define CC1101_VAL_FREQ1_423875 0x4D
#define CC1101_VAL_FREQ0_423875 0x62
#define CC1101_VAL_FREQ2_4200125 0x10
#define CC1101_VAL_FREQ1_4200125 0x27
#define CC1101_VAL_FREQ0_4200125 0x5A
#define CC1101_VAL_FREQ2_413300 0x0F
#define CC1101_VAL_FREQ1_413300 0xE4
#define CC1101_VAL_FREQ0_413300 0x84
#define CC1101_PKTLEN_VALUE 0xFF
// Fixed packet length, FIFO for RX/TX, CRC calculation off, data whitening off
#define CC1101_PKTCTROL0_VALUE 0x00
#define CC1101_PKTCTRL1_VALUE 0x04
#define CC1101_ADDR_VALUE 0x00
#define CC1101_CHANNR_VALUE 0x05
// 9600 bps. Digital channel bandwidth filter: 58 kHz
#define CC1101_MDMCFG4_VALUE 0xC9
#define CC1101_MDMCFG3_VALUE 0x83
// Enable digital DC blocking filter, ASK modulation, disable Manchester encoding, no preamble/sync
#define CC1101_MDMCFG2_VALUE B00110000
// Disable FEC
#define CC1101_MDMCFG1_VALUE B00100010
#define CC1101_MDMCFG0_VALUE 0xF8
// Modem deviation +- kHz
#define CC1101_DEVIATN_25 B01000000 // 25.4 kHz
#define CC1101_DEVIATN_20 B00110101 // 20.63 kHz
#define CC1101_DEVIATN_15_8 B00110010 // 15.87 kHz
#define CC1101_DEVIATN_12_7 B00110000 // 12.7 kHz
#define CC1101_DEVIATN_10 B00100101 // 10.3 kHz
#define CC1101_DEVIATN_7_9 B00100010 // 7.9 kHz
#define CC1101_DEVIATN_7_1 B00100001 // 7.1 kHz
#define CC1101_DEVIATN_6_3 B00100000 // 6.3 kHz
CC1101 radio;
volatile bool packetWaiting = false;
void messageReceived() {
packetWaiting = true;
}
void setup() {
Serial.begin(SERIAL_SPEED);
radio.init();
setFreq(CC1101_VAL_FREQ2_433, CC1101_VAL_FREQ2_433, CC1101_VAL_FREQ2_433);
// disable addr chk
radio.writeReg(CC1101_PKTCTRL1, CC1101_PKTCTRL1_VALUE);
radio.writeReg(CC1101_PKTLEN, CC1101_PKTLEN_VALUE);
radio.writeReg(CC1101_PKTCTRL0, CC1101_PKTCTROL0_VALUE);
radio.writeReg(CC1101_ADDR, CC1101_ADDR_VALUE);
radio.writeReg(CC1101_CHANNR, CC1101_CHANNR_VALUE);
radio.writeReg(CC1101_MDMCFG4, CC1101_MDMCFG4_VALUE);
radio.writeReg(CC1101_MDMCFG3, CC1101_MDMCFG3_VALUE);
radio.writeReg(CC1101_MDMCFG2, CC1101_MDMCFG2_VALUE);
radio.writeReg(CC1101_MDMCFG1, CC1101_MDMCFG1_VALUE);
radio.writeReg(CC1101_MDMCFG0, CC1101_MDMCFG0_VALUE);
radio.writeReg(CC1101_DEVIATN, CC1101_DEVIATN_25);
CCPACKET packet;
packet.length = 0;
radio.setRxState();
uint16_t t = 0;
uint8_t marcState = radio.readStatusReg(CC1101_MARCSTATE) & 0x1F;
Serial.println(marcState);
while (marcState != 0x0D)
{
marcState = radio.readStatusReg(CC1101_MARCSTATE) & 0x1F;
}
Serial.print(F("CC1101 partnum "));
Serial.println(radio.readStatusReg(CC1101_PARTNUM));
Serial.print(F("CC1101 version "));
Serial.println(radio.readStatusReg(CC1101_VERSION));
Serial.print(F("CC1101 marcstate "));
Serial.println(radio.readStatusReg(CC1101_MARCSTATE) & 0x1F);
Serial.println(F("CC1101 initialized"));
attachInterrupt(digitalPinToInterrupt(CC1101_GDO0), messageReceived, FALLING);
}
// http://www.ti.com/lit/an/swra114d/swra114d.pdf
int rssi(char raw) {
uint8_t rssi_dec;
uint8_t rssi_offset = 74;
rssi_dec = (uint8_t) raw;
if (rssi_dec >= 128)
return ((int)( rssi_dec - 256) / 2) - rssi_offset;
else
return (rssi_dec / 2) - rssi_offset;
}
int lqi(char raw) {
return 0x3F - raw;
}
void loop() {
//Serial.println(radio.readStatusReg(CC1101_MARCSTATE) & 0x1F);
if (packetWaiting) {
detachInterrupt(CC1101_GDO0);
packetWaiting = false;
CCPACKET packet;
if (radio.receiveData(&packet) > 0) {
Serial.println(F("Received packet"));
Serial.print(F("lqi: "));
Serial.println(lqi(packet.lqi));
Serial.print(F("rssi: "));
Serial.print(rssi(packet.rssi));
Serial.println(F(" dBm"));
if (packet.length > 0) {
Serial.print(F("packet: len "));
Serial.println(packet.length);
Serial.println(F("data: "));
for (int i = 0; i < packet.length; i++) { Serial.print(packet.data[i], HEX); }
Serial.println();
//Serial.println((const char *) packet.data);
}
}
attachInterrupt(digitalPinToInterrupt(CC1101_GDO0), messageReceived, FALLING);
}
}
void setFreq(uint8_t f2, uint8_t f1, uint8_t f0) {
radio.writeReg(CC1101_FREQ2, f2);
radio.writeReg(CC1101_FREQ1, f1);
radio.writeReg(CC1101_FREQ0, f0);
}
CC1101 piirin ohjelmointi on aika kryptistä ja työlästä. TI:n SmartRF ohjelmalla (kehityskortin mukana, maksullinen) rekisteriarvojen määrittäminen olisi simppeliä. Perus toimintataajuuden rekisteriarvot voi määrittää vaikka näin:
Programming CC1101 is quite crypting and tedious work. By using TI SmartRF application (comes with developer card) defining register values would be much easier. C# code to define carrier frequency CC1101 register values:
#include <math.h>
#define clk_frq 26.0
#define carrier_freq 433.0
double frequencyInMHz = carrier_freq;
double secondByteOverflow = fmod(frequencyInMHz, clk_frq);
double firstByteValue = (double)((frequencyInMHz - secondByteOverflow) / clk_frq);
double thirdByteOverflow = fmod((secondByteOverflow * 255), clk_frq);
double secondByteValue = (double)(((secondByteOverflow * 255) - thirdByteOverflow) / clk_frq);
double excessOverflow = fmod((thirdByteOverflow * 255), clk_frq);
double thirdByteValue = (double)(((thirdByteOverflow * 255) - excessOverflow) / clk_frq);
Serial.print("FREQ2: ");
Serial.println((byte) firstByteValue, HEX);
Serial.print("FREQ1: ");
Serial.println((byte) secondByteValue, HEX);
Serial.print("FREQ0: ");
Serial.println((byte) thirdByteValue, HEX);
C# - CC1101 rekisteriarvot: bps ja taajuus
C# - CC1101 define register values for bps and frequency
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace cc1101
{
public partial class formCC101 : Form
{
const double CC1101_CLK_FREQ = 26;
public formCC101()
{
InitializeComponent();
}
private void txtCF_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) &&
(e.KeyChar != '.'))
{
e.Handled = true;
}
// only allow one decimal point
if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1))
{
e.Handled = true;
}
}
private void buttonCalcCF_Click(object sender, EventArgs e)
{
labelF2.Text = "FREQ2: ";
labelF1.Text = "FREQ1: ";
labelF0.Text = "FREQ0: ";
labelMDMCFG4.Text = "MDMCFG4: ";
labelMDMCFG3.Text = "MDMCFG3: ";
labelBPS.Text = "";
double frequencyInMHz = Double.Parse(txtCF.Text.Replace(".", ","));
double secondByteOverflow = frequencyInMHz % CC1101_CLK_FREQ;
double firstByteValue = (double)((frequencyInMHz - secondByteOverflow) / CC1101_CLK_FREQ);
double thirdByteOverflow = (secondByteOverflow * 255) % CC1101_CLK_FREQ;
double secondByteValue = (double)(((secondByteOverflow * 255) - thirdByteOverflow) / CC1101_CLK_FREQ);
double excessOverflow = (thirdByteOverflow * 255) % CC1101_CLK_FREQ;
double thirdByteValue = (double)(((thirdByteOverflow * 255) - excessOverflow) / CC1101_CLK_FREQ);
labelF2.Text = labelF2.Text + ((byte)firstByteValue).ToString("X");
labelF1.Text = labelF1.Text + ((byte)secondByteValue).ToString("X");
labelF0.Text = labelF0.Text + ((byte)thirdByteValue).ToString("X");
double clockFrequencyMHz = CC1101_CLK_FREQ;
double baudRate = Double.Parse(txtBPS.Text.Replace(".", ","));
double baudRateExponent = 0;
double baudRateMantissa = 0;
for (int tempExponent = 0; tempExponent < 16; tempExponent++)
{
int tempMantissa = (int)((baudRate * Math.Pow(2, 28) / (Math.Pow(2, tempExponent) * (clockFrequencyMHz * 1000000.0)) - 256) + .5);
if (tempMantissa < 256)
{
baudRateExponent = tempExponent;
baudRateMantissa = tempMantissa;
break;
}
}
baudRate = (1000000.0 * clockFrequencyMHz * (256 + baudRateMantissa) * Math.Pow(2, baudRateExponent) / Math.Pow(2, 28));
baudRate = Math.Round(baudRate, 4);
byte mdmcfg4 = Convert.ToByte( "10001100", 2 );
labelMDMCFG4.Text = labelMDMCFG4.Text + ((byte)((mdmcfg4 & 0xf0) | (int)baudRateExponent)).ToString("X");
labelMDMCFG3.Text = labelMDMCFG3.Text + ((byte)baudRateMantissa).ToString("X");
labelBPS.Text = baudRate.ToString();
}
private void textBPS_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) &&
(e.KeyChar != '.'))
{
e.Handled = true;
}
// only allow one decimal point
if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1))
{
e.Handled = true;
}
}
}
}
Kommentit
Tämän blogin kommentit tarkistetaan ennen julkaisua.