RadioEi

From RevSpace
Revision as of 13:18, 10 July 2015 by Luteijn (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

werk in uitvoering (zowel deze pagina als het RadioEi zelf)

Wat is een RadioEi

Het RadioEi is een miniatuur radiobakentje dat in de capsule uit een verrassings-ei is gepropt.

Het RadioEi bestaat uit een 3V batterij (CR2032) in een houdertje dat ooit op een PC-moederbord gezeten heeft, een Atmel ATTiny45 microcontroller, en een HopeRF RFM68CW module


Versies

Proof of Concept

De allereerste versie was niet meer dan het kale RFM68CW bordje met draadjes van een centimeter of 15 eraan gesoldeerd (17,5 cm (ongeveer een kwart golf) voor de antenne) en een halve USB kabel en wat weerstanden om ongeveer 3V van de 5V uit een USB voeding te maken, en als pull-down voor de datalijn. Dit alles in een breadboardje geprikt met de 'control' en 'not-reset' lijnen op 3V en de datalijn via een pull-down weerstand aan GND, en dan met een een kort jumperkabeltje 3V op de 'data' pen zetten om met de hand te seinen.

Arduino

Het handmatige seinen werd al snel vervangen door een arduino(-kloon) om de data lijn te bedienen, en toen was het tijd om uit te zoeken hoe i.p.v. een volledige arduino, een losse ATMega of ATTiny te gebruiken die dan ook nog op 3V kon lopen, zodat er geen gedoe met 5V<->3,3V conversie nodig was

Stand-Alone

Dit bleek helemaal niet zo moeilijk te zijn en na wat prutsen draaide het prototype op een breadbordje al relatief snel. Er was vooral veel doorloop-tijd omdat ik helaas niet ongestraft onbeperkt tijd in het project kan stoppen.

RadioEi v0.99

Kijk ma, geen handen! Breadboardje er tussenuit en een tweede RFM68CW radiomodule met wat vrolijk gekleurde draadjes aan een batterijhouder en een ATT45 in een voetje gesoldeerd. Aan-uit zetten door de batterij in dan wel uit de houder te floepen, en gaan.

Programma ATT45

Hier is een versie van het programma voor de ATT45. De uitgezonden tekst staat aan het einde, die zou ik wel even aanpassen aan je eigen doeleinden.

// pseudo constants; should probably just use defines.
// ---
// using at-tiny with data,ctrl,not reset of the transmitter module on pin 4,3,1
int data = 4;
int ctrl = 3;
int nrst = 1;
// times used when resetting the RF module (in ms)
int reset = 500;
int recover = 500;
// length of a dot in ms
int x=50;
// delay in ms after each cycle of the beacon
int y=1000;

// functions
// ---
// 'letter end'
// add two more delays of x ms, in addition to the one always added at the end of a dot or a dash to give 3 x ms, 
// the inter-character spacing.
void lend () {
  delay(x);
  delay(x);
}

// 'word end'
// add 6 more delays of x ms, in addition to the one always added at the end of a dot or a dash to give 7 x ms, 
// the inter-word spacing.
void wend() {
  delay(x);delay(x);delay(x);
  delay(x);delay(x);delay(x);  
}

// 'word separator'
// add 4 more delays of x ms, in addition to the 3 added by dit() or dah() to give 7 x ms, 
// the inter-word spacing.
void I() {
  delay(x);delay(x);
  delay(x);delay(x);  
}
// TODO: might want need to change to more direct manipulation of the GPIO register?
// send an letter-internal dit (x ms tone and x ms silence)
void di() {
  digitalWrite(data,HIGH);
  delay(x);
  digitalWrite(data,LOW);
  delay(x);
}

// send a letter-terminal dit (x ms tone and 3 x ms silence)
void dit () {
  di();
  lend();
}

//send a letter-internal dah (3 x ms tone and x ms silence)
void da() {
  digitalWrite(data,HIGH);
  lend();
  di();
}

//send a letter-terminal dah (3 x ms tone and 3 x ms silence)
void dah() {
  da();
  lend();
}

// FIXME: morse overzicht: http://mbhs.edu/~jeglick/Images/Information/International%20Morse%20Code.jpg 
// die mist wel wat extenties om meer niet-alfanumerieke tekens te kunnen gebruiken.
// wellicht vergelijken met wat er in
// bv fldigi gebruikt wordt, zodat het baken ook automatisch gedecodeerd kan worden...
int morse_sendchar(char c) {
  switch (toupper(c)) {
   case ' ': I; break;
   case 'A': di();dah(); break; 
   case 'B': da();di();di();dit(); break; 
   case 'C': da();di();da();dit(); break; 
   case 'D': da();di();dit(); break;
   case 'E': dit(); break;
   case 'F': di();di();da();dit(); break;
   case 'G': da();da();dit(); break;
   case 'H': di();di();di();dit(); break;
   case 'I': di();di(); break;
   case 'J': di();da();da();dah(); break;
   case 'K': da();di();dah(); break;
   case 'L': di();da();di();dit(); break;
   case 'M': da();dah(); break;
   case 'N': da();dit(); break;
   case 'O': da();da();dah(); break;
   case 'P': di();da();da();dit(); break;
   case 'Q': da();da();di();dah(); break;
   case 'R': di();da();dit(); break;
   case 'S': di();di();dit(); break;
   case 'T': dah(); break;
   case 'U': di();di();dah(); break;
   case 'V': di();di();di();dah(); break;
   case 'W': di();da();dah(); break;
   case 'X': da();di();di();dah(); break;
   case 'Y': da();di();da();dah(); break;
   case 'Z': da();da();di();dit(); break;
   case '0': da();da();da();da();dah(); break;
   case '1': di();da();da();da();dah(); break;
   case '2': di();di();da();da();dah(); break;
   case '3': di();di();di();da();dah(); break;
   case '4': di();di();di();di();dah(); break;
   case '5': di();di();di();di();dit(); break;
   case '6': da();di();di();di();dit(); break;
   case '7': da();da();di();di();dit(); break;
   case '8': da();da();da();di();dit(); break;
   case '9': da();da();da();da();dit(); break;   
   case '.': di();da();di();da();di();dah(); break;
   case ',': da();da();di();di();da();dah(); break;
   case ':': da();da();da();di();di();dit(); break;
   case '-': da();di();di();di();di();dah(); break;
   case '\'': // fall through to next case, both are apostrophes
   case '`': di();da();da();da();da();dit(); break;
   case '/': da();di();di();da();dit(); break;
   case '|': di();da();di();di();dah(); break; //separation between whole number and fraction: 1.5-> 1|1/2
   case ')': //fall through
   case '(': da();di();da();da();di();dah(); break;
   case '_': di();di();da();da();di();dah(); break; //start and end _underlined_ words;
   case '=': da();di();di();di();dah(); break;
   case '+': // find proper extension to code..
   default : di();di();dah();dah();di();dit(); break; // ?
  } 
}

int morse_send(char * s) {
  // s should be pointer to a NUL terminated string. maybe add sanity check to refuse to send strings
  // longer than an upper limit?
  for (;*s != 0; s++) {
    morse_sendchar(*s);
  }
} 


// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pins we use as outputs.
  pinMode(data, OUTPUT);  
  pinMode(ctrl, OUTPUT); 
  pinMode(nrst, OUTPUT);
  digitalWrite(data,LOW);
  digitalWrite(ctrl,HIGH);
  digitalWrite(nrst,LOW);
  delay(reset);  // generous amount of time to actually reset
  digitalWrite(nrst,HIGH);
  delay(recover);  // generous amount of time to recover from reset and switch to default CW mode
}

// the loop routine runs over and over again forever:
void loop() {
  morse_send("pc1pcl - morse beacon #1 - the quick brown fox jumped over the lazy dog - VVVVV ");
  delay(y);
}

Toekomst

De reset en control lijnen van de RF module zitten aan de ATT45; voor 'standaard' gebruik kunnen ze ook gewoon aan Vcc hangen, maar het is nu ook mogelijk om de RFM68CW om te zetten naar andere frequenties en modes en bijvoorbeeld RTTY via FSK te gaan versturen, of wellicht een botte manier van FM modulatie door de carrier frequentie van de CW-mode on-the-fly te veranderen. Er is ook een terug-meld-lijn die evt aan de ATT45 gekoppeld kan worden, en dan zouden er nog net twee pootjes over zijn om een seriele poort mee te knutselen om bijv een ubloc GPS mee te besturen/uit te lezen, of om met een tweede microcontroller te praten die andere functies implementeert. Genoeg ideeen voor verdere ontwikkeling dus. Oh en een aan-uit schakelaartje is misschien ook handig, scheelt gepruts met de batterij in/uit de houder halen...

Testen

Met een amateur(zend)ontvanger is het CW signaal prima te ontvangen door het gebouw en op de parkeerplaats. Het zendertje is ook op een FM porto te ontvangen, maar piept dan dus niet, maar drukt de ruis weg in het ritme van de morsetekens/laat het squelch ledje knipperen. Vanaf de vensterbank thuis was het signaal bij een korte wandeling door de wijk nog wel te ontvangen, volgende test zou kunnen zijn om met het ei wat hoger, bijvoorbeeld op het dak, te plaatsen en dan te kijken of het bijvoorbeeld op de HAB-ontvanger van RevSpace te horen is, of hoever weg je moet fietsen om het niet meer te horen. Als het weer een beetje meewerkt, zou het RadioEi ook per vlieger de lucht in kunnen, om al dan niet gedropt te worden per parachute...