Pi Crust : faciliter l’accès aux entrées sorties du Raspberry Pi

Pi Crust sur une carte Raspberry Pi (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/10/photo02 NULL.jpg)Si vous avez un Raspberry Pi, vous vous êtes peut-être rendus compte qu’utiliser les entrées sorties comme le port GPIO est beaucoup moins facile que sur une platine Arduino par exemple. Fort de ce constat, Joe Waynes a conçu une petite carte qui se superpose au Raspberry (http://picru NULL.st/) sans en modifier la taille ou l’allure, juste en ajoutant quelques millimètres d’épaisseur.

Joe ne vend pas ce circuit, mais en met les fichiers pour faire le circuit-imprimé à disposition de tous. Il a aussi contacté un fabricant de circuits imprimés qui a décidé de le réaliser pour 4,6 USD (http://store NULL.oshpark NULL.com/products/pi-crust-v4). La carte permet ainsi de séparer les accès aux différents périphériques dont le GPIO, le bus I2C, le connecteur SPI, l’UART et des broches d’alimentation… Attention toutefois, cette carte est uniquement passive et n’offre aucune protection sur les entrées sorties du micro-processeur. Les ports GPIO par exemple sont prévus pour 3,3V et peuvent souffrir avec du 5V…

Merci à Ars Technica (http://arstechnica NULL.com/business/2012/10/pi-crust-breakout-board-makes-it-easy-to-get-peripherals-on-raspberry-pi/) pour l’information.

Station météo à mémoire avec Arduino et DHT11

Ecran Station météo Arduino (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/10/100_3301 NULL.jpg)A la maison j’ai une petite “station météo” Oregon Scientific BAR310HG avec un capteur distant sans fil. Elle m’a donné toute satisfaction pendant 5 ans pour son prix très correct, mais les conditions du climat tropical commence à avoir raison des contacts et le capteur sans-fil ne fonctionne plus… Ce type de produit là n’étant pas fait pour être réparé je me suis fait une raison.

Capteur Température Humidité DHT11 (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/10/100_3303 NULL.jpg)En cherchant après des composants électroniques à Hong Kong, je suis tombé sur la série de capteurs DHT11 et DHT22 qui sont à la fois économique et suffisamment performant pour un usage domestique. Le DHT22 est plus précis mais un peu plus cher, pour mes premier essais j’ai donc choisi le modèle moins cher.

Voici un premier jet d’un programme pour Arduino qui va interroger le capteur, affiche les valeurs en temps réel, mais surtout les sauvegarde dans la mémoire EEPROM pour en faire des statistiques. L’avantage de les sauvegarder en EEPROM c’est qu’on peut faire une mesure, éteindre la station météo, la rallumer bien plus tard pour faire une autre mesure et avoir la moyenne. Pour des raisons de rapidité de traitement seules 10 valeurs sont sauvegardées, mais la mémoire disponible en permet bien d’avantage.

La commande est simple, il suffit d’appuyer brièvement sur le bouton pour sauvegarder une valeur. Un appui long (plus d’une seconde) efface toutes les valeurs en mémoire.

Une version plus évoluée et utilisant un capteur DHT22 sera prochainement proposée en kit sur la boutique (http://xv4y NULL.radioclub NULL.asia/boutique/). Elle utilisera une horloge RTC pour faire de statistiques sur une période calendaire. Les sauvegardes seront interrogables par port série, et la possibilité d’interroger un capteur à distance via des modules radio 433 MHz sera incluse.

/*
Arduino Thermometer and Humidity display with EEPROM saved statistics using DHT11 sensor v1.00
By Yannick DEVOS - XV4Y
http://xv4y.radioclub.asia/

Copyright 2012 Yannick DEVOS under GPL 3.0 license
Any commercial use or inclusion in a kit is subject to author approval

====
This program sense and displays the current temperature and relative humidity
It saves 10 values in memory when button is pressed and display an average
Pressing the button more than 1 second will erase all the values
Values are stored in EEPROM, you can do measuring, turn off the Arduino, then do other measuring the day after...

The display is on a 16x2 LCD Display with HD44780 compatible driver, use the traditional 4 bits interface on pins 10, 9, 8, 7, 6, 5

In order to compile this program with Arduino 1.0.1, you will need to install 3 libraries :
- Arduino Bounce Library
http://www.arduino.cc/playground/code/bounce
- New LiquidCrystal
https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home
- DHT-sensor Library by Adafruit
https://github.com/adafruit/DHT-sensor-library

====
Revision history :
v1.00    2012-10-26
         First release
====
The DHT11 Sensor need to be connected as described here below
- Connect pin 1 (on the left) of the sensor to +5V
- Connect pin 2 of the sensor to whatever your DHTPIN is (here pin D12)
- Connect pin 4 (on the right) of the sensor to GROUND
- Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor
We also need a push button on pin D2.

====
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You can download a copy of the GNU General Public License at <http://www.gnu.org/licenses/>
*/

#include <Wire.h>
#include <EEPROM.h>
#include <LiquidCrystal.h>
#include <Bounce.h>
#include "DHT.h"

#define DHTPIN 12     // What pin we have connected the DHT sensor
#define BUTTON 2      // What

#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal lcd(10, 9, 8, 7, 6, 5);  // You can change this settings to your convenance, please see the library documentation
Bounce button_debounce = Bounce( BUTTON, 10 ); 

int t = 0, h = 0, a = 0, b = 0, avg_t = 0 , avg_h = 0, saved_t = 0, saved_h = 0;
int current_address = 1, i_address = 1;

void setup() {
  lcd.begin(16,2);
  lcd.home ();

  dht.begin();

  pinMode(BUTTON,INPUT_PULLUP);

  // We read where was the last saved value
  current_address = int(EEPROM.read(0));

}

void loop() {
  button_debounce.update ( );

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  h = int(dht.readHumidity());    // we convert to integer since the DHT11 has not enough precision anyway
  t = int(dht.readTemperature());

  // check if returns are valid, 0 degrees and 0 percent humidity is impossible with the DHT11 sensor...
  if (h == 0 && t == 0) {
    lcd.clear ();
    lcd.home ();
    lcd.print("Sensor Error");
    delay(1000);
    lcd.clear ();
    lcd.home ();
  } else {
    lcd.setCursor ( 0, 0 );
    lcd.print("T:    "); 
    lcd.setCursor ( 3, 0 );
    lcd.print(t);
    lcd.setCursor ( 5, 0 );
    lcd.print("*C");
    lcd.setCursor ( 0, 1 );
    lcd.print("H:    ");
    lcd.setCursor ( 3, 1 );
    lcd.print(h);
    lcd.setCursor ( 5, 1 );
    lcd.print("%");
  }

 int button_status = button_debounce.read();

 // If the button is pressed
 if (button_status == LOW) {
   if (button_debounce.duration()>1000) {  // For more than 1 second we erase the saved values in the EEPROM
     lcd.clear ();
     lcd.home ();
     lcd.print("Erasing");
     lcd.setCursor ( 0, 1 );
     lcd.print("All values");

     for (int i = 0; i <= 45; i++)  // We erase the 10 sets of values
        EEPROM.write(i, 0);
     current_address = 1;
     EEPROM.write(0, 1);

     delay(1000);
     lcd.clear ();
     lcd.home ();
   } else {                                // For shorter we save the value in the EEPROM
     lcd.clear ();
     lcd.home ();
     lcd.print("Saving value");
     lcd.setCursor ( 0, 1 );
     lcd.print("in memory ");
     lcd.setCursor ( 10, 1 );
     lcd.print(round((current_address/4)+1));

     EEPROM.write(current_address, byte(t & 0xFF));
     EEPROM.write(current_address+1, byte(t >> 8));
     EEPROM.write(current_address+2, byte(h & 0xFF));
     EEPROM.write(current_address+3, byte(h >> 8));
     current_address = current_address + 4;
     if (current_address >= 41) current_address = 1;
     EEPROM.write(0, byte(current_address & 0xFF));

     delay(500);
     lcd.clear ();
     lcd.home ();
   }
 }

 // Here we read the saved values in the EEPROM and do the average
 avg_t = 0;
 avg_h = 0;
 for (i_address = 1; i_address <= 41; i_address = i_address + 4) {

   a = EEPROM.read(i_address);
   b = EEPROM.read(i_address+1);
   saved_t = (b << 8 | a);
   if (saved_t != 0)
     if (avg_t == 0) {
       avg_t = saved_t;
     } else {
       avg_t = (saved_t + avg_t) / 2;
     };

   a = EEPROM.read(i_address+2);
   b = EEPROM.read(i_address+3);
   saved_h = (b << 8 | a);
   if (saved_h != 0)
     if (avg_h == 0) {
       avg_h = saved_h;
     } else {
       avg_h = (saved_h + avg_h) / 2;
     };
 }

 // Here we display the averaged values
 lcd.setCursor ( 8, 0 );
 lcd.print("Avg    "); 
 lcd.setCursor ( 12, 0 );
 if (avg_t != 0) {  // Display only when the value is significant
   lcd.print(avg_t);
 } else {
   lcd.print("--");   
 }
 lcd.setCursor ( 14, 0 );
 lcd.print("*C");
 lcd.setCursor ( 8, 1 );
 lcd.print("Avg    ");
 lcd.setCursor ( 12, 1 );
 if (avg_h != 0) {  // Display only when the value is significant
   lcd.print(avg_h);
 } else {
   lcd.print("--");   
 }
 lcd.setCursor ( 14, 1 );
 lcd.print("%");

}

L’IC-7410 en promotion…

Je suis tombé dessus un peu par hasard. Aux USA Icom offre 150$ de remise sur l’IC-7410. Cette remise est répercutée par HRO (http://www NULL.hamradio NULL.com/detail NULL.cfm?pid=H0-010984) (le meilleur prix), Gigaparts (http://www NULL.gigaparts NULL.com/store NULL.php?action=profile&sku=ZIC-7410) et Universal-Radio (http://www NULL.universal-radio NULL.com/catalog/hamhf/0748 NULL.html). En Europe c’est plus compliqué. Chez Icom-France, la page principale montre une remise de 100€ (http://www NULL.icom-france-boutique NULL.com/produit-ic-7410 NULL.php), mais comme ils étaient déjà plus cher que tous leurs revendeurs, le prix Icom IC-7410 vu de face (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/10/IC-7410 NULL.jpg)devient juste le même qu’ailleurs soit 1899€, mais c’est port compris, ce qui n’est pas toujours clair ailleurs. Chose étonnante, Batima liste l’IC-7410 à 1900€ (http://www NULL.batima-electronic NULL.com/spip NULL.php?article420) mais annonce une promotion à 1800€ sur une autre page (http://www NULL.batima-electronic NULL.com/spip NULL.php?article377) sans dates ni conditions.  Chez Radio 33 il est aussi à 1890€ avec 25€ de port en sus. Chez WiMo, rien mais le prix n’est pas mauvais. Chez Folie-Numérique il faudrait être fou pour acheter car il est à plus de 2000€ TTC. La palme du meilleur prix revient à E-Shopamateur qui le liste à 1699€ hors frais de port (http://www NULL.e-shopamateur NULL.lu/icom NULL.html), mais ceux-ci sont en principe inférieurs à 25€.

Enfin, cela m’amenait à me dire qu’Icom doit s’être rendu compte de son petit loupé avec ce poste pour officiellement faire un tel taux de remise sur un poste très récent. Je ne parle pas de différence entre le prix public et le prix réellement constaté, mais bien d’une remise constructeur supplémentaire. Il faut dire qu’avec l’arrivée du FTDX-3000 (http://xv4y NULL.radioclub NULL.asia/2012/10/16/les-premiers-ftdx-3000-de-yaesu-livres-aux-usa/), l’IC-7410 doit se sentir à l’étroit. Plus cher mais moins performant et moins bien équipé en filtre que le TS-590s, le band-scope sur l’écran noir et banc ne suffit pas à séduire les DXers pour qui les filtres optionnels nécessaires alourdiront la note. D’un côté le nouveau Yaesu est certes bien plus cher, mais avec un niveau de performances annoncé bien plus élevé, un équipement d’origine bien plus riche et des fonctionnalités très avancées avec un band-scope flexible sur un écran couleur.

Pour ma part, sans parler du côté pécuniaire, je ne suis pas sûr que je troquerais mon TS-590s (http://www NULL.hamradio NULL.com/detail NULL.cfm?pid=H0-010818) contre quoi que ce soit d’autre en ce moment. L’ergonomie est pour moi le point le plus important (tant que le reste n’est pas mauvais bien entendu), et j’avoue que sur ce sujet j’ai été totalement séduit par Kenwood.

Sinon, si vous êtes à l’affut des bonnes affaires, jetez un oeil sur l’IC-7000 qui est en fin de vie avec l’arrivée proche du 7100. Ce n’est peut-être pas le meilleur poste pour lutter contre les signaux adjacents dans un concours (son AGC semble pomper beaucoup) mais pour le prix il offre pas mal à son utilisateur.

Belle ouverture sur 10 mètres ce matin

Une fois les enfants déposés à l’école à 7 heures, je monte au bureau pour répondre aux différents messages et travailler un peu. Toutefois je m’autorise à prendre quelques minutes pour faire un petit tour d’écoute sur les bandes. Il est environ 00h30 utc et cela s’avérera être une bonne idée!

En général, la journée, je commence toujours par les bandes hautes. Si c’est fermé ça va vite, si c’est ouvert la probabilité que ce soit du DX est plus importante. Je tombe d’abord sur quelques stations BA et BD qui opèrent en split et empilent les QSO avec les USA. J’écoute un peu leur fréquence de réception et ô surprise j’arrive moi aussi à recevoir les stations d’Amérique du Nord. Les signaux ne sont pas très épais, et la Chine c’est bien plus au Nord (et à l’Est) que moi. Le problème c’est que sur ma verticale je ramasse beaucoup de QRM avec des signaux divers à plus de S9. J’essaye de passer sur la Moxon (qui est un dipôle sur 10 mètres) mais c’est pire car les signaux reçus descendent plus que le QRM…

P29VCX op SM6VCX 2011 (http://p29ni NULL.weebly NULL.com/)Je continue à balayer la bande pour tomber sur P29VCX (http://dx-world NULL.net/2012/p29vcx-bougainville-island-oc-135/) qui m’arrive 599 avant qu’il ne soit annoncé sur le DX-Cluster. Ce doit être notre troisième QSO en 2 jours. Pas un new-one mais une nouvelle entité pour cette année du DX Marathon et je n’ai pas P29 sur plusieurs bandes. Je continuer à monter pour tomber encore une fois sur une station avec de forts signaux sur 28,017 MHz : c’est Scotty W7SW (http://www NULL.qrz NULL.com/db/W7SW) avec qui je fais régulièrement QSO sur différentes bandes. Il est ma première station NA sur 10 mètres, et je suis content que ce soit lui! Je m’installe un peu plus haut et commence à lancer appel. Assez rapidement me répondent des stations JA (avec beaucoup de QSB) et Dominique de FK8CE (http://qrz NULL.com/db/fk8ce) un autre habitué avec qui on a du faire QSO sur 5 bandes au moins.

Finalement je ne contacterai que 3 autres stations NA dont une avec des signaux très très faibles. Comme souvent avec un chemin polaire, la propagation devait être très très sélective. De plus le QRM omniprésent sur 28MHz et ma puissance d’émission limitée à 100W ne facilitent pas les QSO. Demain j’essayerai quand même de refaire un tour sur le 10 mètres aux mêmes heures…

Amplificateur QRP en classe D, E et F

Les amateurs d’opérations avec de très petits puissances (QRP) sont toujours à la recherche de l’efficacité énergétique maximum. En effet, souvent le QRP est synonyme de portable, et l’encombrement des batteries (ou de la source d’alimentation) doit être réduit au maximum.

Amplificateur ClasseE, schéma par NA5N (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/10/Schéma_classe_E_NA5N NULL.jpg)Alors que la plupart des transceivers HF du commerce utilisent des amplificateurs en classe B (http://fr NULL.wikipedia NULL.org/wiki/Classes_de_fonctionnement_d), voire parfois en classe A (http://fr NULL.wikipedia NULL.org/wiki/Classes_de_fonctionnement_d) pour les hauts de gamme, les classes D, E et F sont devenus le nouveau Eldorado des concepteurs d’amplificateurs de puissance pour postes QRP. Avant de continuer, il est important de noter que l’éclosion de ces technologies n’est pas due au seul travail des amateurs. En effet, à part la télégraphie, il est un autre domaine des radiofréquences où la linéarité n’est pas requise comme en BLU, c’est celui de la transmission de données dans les technologies de téléphonie mobile (GSM, CDMA…). Là encore, contrairement aux applications FM ou RADAR qui peuvent elles aussi se passer de linéarité, c’est la consommation énergétique qui prime pour garantir la meilleure autonomie du terminal.

Parmi les différents projets de kits électroniques que j’ai en tête il y en a qui consiste à proposer un émetteur QRSS (une balise) utilisant un DDS contrôlé par micro-contrôleur MSP430. Il y a d’un côté la partie “modulation” par le micro-contrôleur qui est déjà au point, ensuite la partie contrôle du circuit DDS sur laquelle je vais plancher dès que j’aurais reçu mes échantillons, et puis il y a la partie amplificateur de puissance pour laquelle je suis toujours en recherche d’information.

J’aimerai bien faire produire 1W à cet amplificateur, histoire d’avoir de la marge et de pouvoir le faire fonctionner confortablement à des niveaux inférieurs si nécessaire. Plusieurs schémas existent déjà et me plaisent bien, mais conformément à mon habitude j’aime bien beaucoup me documenter avant de me lancer dans un projet. Je partage donc avec vous quelques documents glanés au fil de mes recherches. Tout d’abord il y a cette présentation du très prolixe Dan Tayloe N7VE (http://www NULL.norcalqrp NULL.org/files/class_e_amplifiers NULL.pdf) qui part des notions de base des amplificateurs classe E pour parler de leurs défauts et surtout des solutions qui existent pour compenser ces défauts. Ensuite, cet article de Paul Harden NA5N couvre les classes C, D, E et F (http://www NULL.aoc NULL.nrao NULL.edu/~pharden/hobby/_ClassDEF1 NULL.pdf) en comparant les amplificateurs MOSFET aux classiques amplificateurs à transistors bipolaires. Plus théorique, elle est un must pour ceux qui sont étrangers à ces technologies. Pour finir, celui-ci par Gerard Borg est plus pratique (http://users NULL.cecs NULL.anu NULL.edu NULL.au/~Gerard NULL.Borg/engn4545_borg/VHFPA/2N7000/2N7000_CLASSE NULL.pdf), et je pense qu’il servira de base à mes travaux….

Photos de la Lune – 20 octobre 2012

Voici quelques photos de notre satellite naturel prises hier soir. Le ciel était encore nuageux (c’est la saison des pluies…) et il était impossible d’observer le ciel profond. Paul et moi nous sommes rabattus sur la Lune et avons fait quelques clichés du premier quartier. Les contrastes sont très forts et c’est toujours un très beau spectacle de voir le soleil se lever sur les reliefs des cratères. Une difficulté des prises de vue lors d’une lune partiellement illuminée c’est que la webam a du mal à régler son ouverture. Certaines parties de l’image peuvent être brûlées et d’autres sous-exposées. Il faut que je cherche comment faire ce réglage manuellement dans BTV.

Le matin nous avions essayé de faire quelques photos de Vénus mais le ciel partiellement nuageux et l’heure un peu tardive ont fait que le fond du ciel n’était plus foncé du tout. Visuellement ça allait mais la webcam n’arrivait pas à régler son exposition…

Il va de soit que toutes ces photos ne vont pas rivaliser avec les photos de l’observatoire du Pic du Midi, mais je suis toujours amusé de voir ce que l’on peut faire avec une simple webcam à 5 euros montée au foyer. Le plus dur restant la mise au point, et c’est malheureusement critique dans la qualité des images…

Lune 20 octobre 2012 - XV4Y (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/10/BTV-004 NULL.jpg)

Lune 20 octobre 2012 - XV4Y (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/10/BTV-008 NULL.jpg)

Lune 20 octobre 2012 - XV4Y (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/10/BTV-006 NULL.jpg)

Lune 20 octobre 2012 - XV4Y (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/10/BTV-003 NULL.jpg)

Macros pour contrôler les mémoires vocales du TS-590s durant les contests

Pour les concours, les opérateurs de pointe se doivent d’optimiser l’ergonomie de leur station aux petits oignons. La plupart des logiciels de log pour les concours permettent de concevoir des macros pour commander le transceiver et automatiser les tâches répétitives. DK5TX partage avec nous son fichier de script LUA qui permet de commander les mémoires vocales du TS-590s (le module VGS-1) à partir de Win-Test (http://5tx NULL.de/?p=998).

Pour ma part, j’utilise N1MM depuis bientôt un an mais j’avoue que je ne me suis pas encore habitué aux macros. SM0MDG décrit dans ce document comment configurer le cahier de trafic de N1MM pour commander les mémoires vocales du TS-590s (http://se0x NULL.info/docs/TS-590+N1MM-settings NULL.pdf).

Facade TS-590s (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/09/1873_800_350 NULL.jpg)Un dernier rappel, si vous cherchez des informations sur le TS-590s, le premier réflexe doit être de consulter l’aide-mémoire TS-590s Resources Page que Ian de G3NRW (http://homepage NULL.ntlworld NULL.com/wadei/ts-590s NULL.htm) tiens à jour. Ian fait un excellent travail de compilation et d’indexation sur toutes les informations qui touchent au Kenwood TS-590s.

Balise WSPR autonome avec MSP430 – le code source

[GTranslate]

Un kit pour ce circuit de générateur de balise WSPR sera bientôt disponible (http://xv4y NULL.radioclub NULL.asia/boutique/?slug=product_info NULL.php&products_id=30).

Ca m’a pris plus de temps que prévu pour publier le code source de mon générateur WSPR à MSP430 pour la balise QRSS de QRP Labs. Le programme “en production” est stable et fonctionne plusieurs jours d’affilée sans problèmes avec de bons reports (spots) sur WSPR. Le problème vient d’un bogue dans le mode debugging justement, les sorties sur port série sensées aidées à la mise au point ne fonctionne pas bien. Ce bogue résulte à la fois d’un problème de l’IDE Energia (au niveau du compilateur certainement) et d’une utilisation trop importante de la SRAM quand je compile le programme en incluant la librairie Serial. Difficile à résoudre, j’ai passé plusieurs jours à essayer d’optimiser les variables et l’utilisation de la RAM mais sans succès. Je vous livre donc le code “tel que” en sachant que le bogue n’est pas gênant en production.

Pour modifier votre balise QRSS en balise autonome WSPR rien de bien compliqué. Il faut construire un petit circuit selon le schéma ci-dessous. En utilisant un LaunchPad les circuits des LED, contacteurs et quartz sont déjà présents. Il faut y ajouter de quoi :

  • alimenter le MSP430G2553 du LaunchPad en 3,3V
  • créer une tension analogique à 4 niveaux grâce à une échelle R-2R à partir des sorties P2.1 et P2.2
  • alimenter en +5V l’étage PA de la balise uniquement quand c’est nécessaire grâce à un transistor BC548 (ou équivalent) connecté sur la sortie P2.0

Schéma générateur balise autonome WSPR à MSP430 (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/09/WSPR_balise_schéma NULL.png)

Sur le circuit de la balise par elle-même, rien de compliqué. Les modifications sont résumées sur le schéma suivant et consiste à :

  • Retirer le micro-contrôleur ATTiny8
  • Récupérer le +5V, la masse et le contrôle de la LED “varicap” sur le connecteur DIL8
  • Dessouder la patte +5V du potentiomètre de polarisation (bias) du transistor FET du PA pour la connecter sur le transistor BC548
  • Procéder à un nouvel alignement de la puissance de sortie du PA,
  • Procéder à un nouvel alignement de l’excursion en fréquence (shift) pour qu’elle soit au total de 6Hz
  • Procéder à un nouveau réglage de la fréquence pour être dans la bande WSPR (autour de 10 140 200 Hz sur 30 mètres)

Modifications de la balise QRSS QRP Labs pour WSPR - XV4Y (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/10/Kit-WSPR-Mod-balise NULL.jpg)

Pour compiler le code il vous faut bien entendu un LaunchPad avec un MSP430G2253 (http://xv4y NULL.radioclub NULL.asia/2012/04/27/les-micro-controleurs-msp430-de-texas-instruments/). L’environnement de développement Energia correctement installé sur votre micro-ordinateur. La bibliothèque RTC que j’ai développée (http://xv4y NULL.radioclub NULL.asia/2012/05/22/bibliotheque-rtc-pour-le-msp430/) doit aussi être installée dans le répertoire de vos documents Energia. Il vous faut ensuite modifier les paramètre d’indicatif (callsign), de carré Locator et de puissance. Ni la compilation ni le téléchargement ne doivent produire d’erreurs. Une fois le LaunchPad programmé, je vous conseille de placer en position ouverte tous les cavaliers (jumpers) reliant le circuit de programmation-émulation au micro-contrôleur.

L’utilisation du programme par lui même est simple. Vous le mettez sous tension, les deux LEDs rouges et jaunes du LaunchPad vont clignoter alternativement assez rapidement. Le générateur est mode “attente de synchro” et transmet une séquence de test durant au total 30 secondes permettant de vérifier les différentes fréquences symboles et l’extinction du PA.

Ensuite, en utilisant une horloge précise (celle de votre GPS, horloge DCF-77 ou ordinateur synchronisé par NTP), vous appuyez sur le bouton S2 du LaunchPad juste quand l’horloge passe à la seconde zéro d’une minute paire.

Le générateur se met alors en mode “balise” et va transmettre tout de suite une première séquence WSPR. La séquence finie la LED jaune se met à clignoter très rapidement. Si vous appuyez sur le bouton S2 à ce moment, la balise passera à nouveau en émission à la prochaine minute paire. Sinon, elle passera en émission aléatoirement suivant le paramètre que vous avez donné, par défaut le taux est de 20% (tx_rate = 5).

Chez moi, l’horloge reste bonne pendant au moins 72 heures. Après cela elle prend environ une seconde de retard, ce qui suffit à faire que les stations les plus lointaines ne décodent plus la séquence WSPR. La remettre à l’heure ne prend que quelques minutes. L’expérience du GPS montre que sauf à partir dans des solutions complexes et coûteuses (http://www NULL.oe1ifm NULL.at/index NULL.php?option=com_content&view=article&id=49&Itemid=56), atteindre une meilleure stabilité effective reste difficile.

/* WSPR Static Generator for MSP430G2553
 * Code for Energia 008
 
 * By Yannick DEVOS - XV4Y - May-October 2012
    http://xv4y.radioclub.asia/

    Copyright 2012 Yannick DEVOS under GPL 3.0 license
    Any commercial use or inclusion in a kit is subject to author approval
 
 * Based on code by DH3JO Martin Nawrath for WSPR sequence encoding

====
 * Ouput on 2 bits PinA and PinB
 * PTT_key output allows to turn on/off the TX PA while sending
 * Mirror on LED1 and LED2 du LaunchPad for testing
 * Output to Serial for testing
 * Using an R-2R ladder it makes the G0UPL/G0XAR beacon frequency shift

====
Revision history :
v1.00    2012-10-18
         First release

====
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You can download a copy of the GNU General Public License at <http://www.gnu.org/licenses/>
*/

// Here modify to your taste or needs

#define PTT_key 8
#define wsprPinA 10
#define wsprPinB 9
#define LEDPinA 14
#define LEDPinB 2
#define StartBtn 5

const char call[] = "XV4Y ";
const char locator[] = "OK20";
const byte power = 20;
const char tx_rate = 5;

// Be carefull, this is only for debugging.
// If you enable this in production, the clock will drift to much (5 seconds in 10 minutes)
//#define SERIAL_OUT_INFO

// This is in case you use a MSP430 that does not have Hardwart UART. TimerSerial works great but bring a lot of clock drift. Replace each "Serial" object call in the code by mySerial.
/*
#ifdef SERIAL_OUT_INFO
#include <TimerSerial.h> 
TimerSerial mySerial;
#endif
*/

// Here under don't touch anything unless you know what you do

#include <legacymsp430.h>
#include <sRTC.h> // Library for RTC clock with MSP430

const char SyncVec[162] = {
  1,1,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,
  1,1,0,0,1,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,1,0,1,0,1,0,1,0,1,0,0,1,0,0,1,0,1,1,0,0,0,1,1,0,1,0,1,0,
  0,0,1,0,0,0,0,0,1,0,0,1,0,0,1,1,1,0,1,1,0,0,1,1,0,1,0,0,0,1,1,1,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,0,
  0,0,0,1,1,0,1,0,1,1,0,0,0,1,1,0,0,0
};

boolean force_send = 1;  // The first time the beacon is turned on it will send a sequence
byte symbol, bb, begin_sec;
int begin_chunk;

byte c[11];                // encoded message

byte sym[170];             // symbol table 162
byte symt[170];            // symbol table temp
unsigned long n1;          // encoded callsign
unsigned long m1;          // encodes locator

#ifdef SERIAL_OUT_INFO
#endif
RealTimeClock myClock;

//******************************************************************
// Defining pins mode
// Encoding the WSPR sequence

void setup() {
  pinMode(PTT_key, OUTPUT);
  pinMode(wsprPinA, OUTPUT);
  pinMode(wsprPinB, OUTPUT);
  pinMode(LEDPinA, OUTPUT);
  pinMode(LEDPinB, OUTPUT);
  pinMode(StartBtn, INPUT_PULLUP);

  #ifdef SERIAL_OUT_INFO
  Serial.begin(9600);
  Serial.println("\n* MSP430 WPSR beacon"); 
  #endif

  digitalWrite( PTT_key, LOW );
  digitalWrite( wsprPinA, LOW );
  digitalWrite( wsprPinB, LOW );

  digitalWrite( LEDPinA, HIGH );
  digitalWrite( LEDPinB, HIGH );

  prepare_sequence();

  #ifdef SERIAL_OUT_INFO
  Serial.println("* Wait clock is set. Sending test sequence.");
  #endif
  begin_chunk = myClock.RTC_chunk;
  begin_sec = myClock.RTC_sec;
  while(digitalRead(StartBtn)) {
    // This is for blinking LED fast
    if ((myClock.RTC_chunk-(begin_chunk+15))%60==0)
      digitalWrite( LEDPinA, HIGH );
    if ((myClock.RTC_chunk-(begin_chunk+30))%60==0)
      digitalWrite( LEDPinB, HIGH );
    if ((myClock.RTC_chunk-(begin_chunk+45))%60==0)
      digitalWrite( LEDPinA, LOW );
    if ((myClock.RTC_chunk-(begin_chunk+60))%60==0)
      digitalWrite( LEDPinB, LOW );
    
    // We also send a test sequence to help calibrate the transmitter
    if ((myClock.RTC_chunk-(begin_chunk+0))%240==0) 
      send_test(begin_sec);

   };
  randomSeed(myClock.RTC_chunk);
  myClock.Set_Time(0,0,0);
};

//******************************************************************
// Here starts the actual sequence sending

void loop() {
  #ifdef SERIAL_OUT_INFO
  Serial.print("Time:");
  Serial.print(myClock.RTC_min, DEC);
  Serial.print(":");
  Serial.print(myClock.RTC_sec, DEC);
  Serial.print(".");
  Serial.println(myClock.RTC_chunk, DEC);
  #endif

  digitalWrite( PTT_key, LOW );

  digitalWrite( wsprPinB, LOW );
  digitalWrite( LEDPinB, LOW );

  digitalWrite( wsprPinA, LOW );
  digitalWrite( LEDPinA, LOW );

  begin_chunk = myClock.RTC_chunk;
  
  #ifdef SERIAL_OUT_INFO
  Serial.println("* Waiting 1st sec of even mins.");
  #endif

  while (!(myClock.RTC_sec==1 && (myClock.RTC_min%2)==0)) {  // We start each first second of even minutes
    if ((myClock.RTC_chunk-(begin_chunk+10))%20==0) digitalWrite( LEDPinA, HIGH );
    if ((myClock.RTC_chunk-(begin_chunk+20))%20==0) digitalWrite( LEDPinA, LOW );
    if (!digitalRead(StartBtn)) force_send = 1;  // Pressing the button while in wait mode force the sequence to start next time
  };
  
  if (random(tx_rate+1)==tx_rate || force_send) {  // In order to minimize band occupation, randomly start the transmission depending on tx_rate
    force_send = 0;
    digitalWrite( PTT_key, HIGH );
    send_sequence();
    #ifdef SERIAL_OUT_INFO
    Serial.println("\n* End");
    #endif
  } else {
    // If not, we wait around 1 sec so we don't go through this too early...
    digitalWrite( PTT_key, LOW );
    begin_chunk = myClock.RTC_chunk;
    while ( ((256+myClock.RTC_chunk-begin_chunk)%256)<220 ) {
      delay(0);
    };
  };
};

/* Functions declaration
 * This code by DH3JO
 * KHM 2009 /  Martin Nawrath
 * Kunsthochschule fuer Medien Koeln
 * Academy of Media Arts Cologne
*/


//******************************************************************
// normalize characters 0..9 A..Z Space in order 0..36
char chr_normf(char bc ) {
  char cc=36;
  if (bc >= '0' && bc <= '9') cc=bc-'0';
  if (bc >= 'A' && bc <= 'Z') cc=bc-'A'+10;
  if (bc == ' ' ) cc=36;

  return(cc);
}

//******************************************************************
void encode_call(){
  unsigned long t1;

  // coding of callsign
  n1=chr_normf(call[0]);
  n1=n1*36+chr_normf(call[1]);
  n1=n1*10+chr_normf(call[2]);
  n1=n1*27+chr_normf(call[3])-10;
  n1=n1*27+chr_normf(call[4])-10;
  n1=n1*27+chr_normf(call[5])-10;

  // merge coded callsign into message array c[]
  t1=n1;
  c[0]= t1 >> 20;
//  t1=n1;
  c[1]= t1 >> 12;
//  t1=n1;
  c[2]= t1 >> 4;
//  t1=n1;
  c[3]= t1 << 4;
}

//******************************************************************
void encode_locator(){

  unsigned long t1;
  // coding of locator
  m1=179-10*(chr_normf(locator[0])-10)-chr_normf(locator[2]);
  m1=m1*180+10*(chr_normf(locator[1])-10)+chr_normf(locator[3]);
  m1=m1*128+power+64;

  // merge coded locator and power into message array c[]
  t1=m1;
  c[3]= c[3] + ( 0x0f & t1 >> 18);
//  t1=m1;
  c[4]= t1 >> 10;
//  t1=m1;
  c[5]= t1 >> 2;
//  t1=m1;
  c[6]= t1 << 6;

}
//******************************************************************
// convolutional encoding of message array c[] into a 162 bit stream
void encode_conv(){
  int bc=0;
  int cnt=0;
  int cc;
  unsigned long sh1=0;

  cc=c[0];

  for (int i=0; i < 81;i++) {
    if (i % 8 == 0 ) {
      cc=c[bc];
      bc++;
    }
    if (cc & 0x80) sh1=sh1 | 1;

    symt[cnt++]=parity(sh1 & 0xF2D05351);
    symt[cnt++]=parity(sh1 & 0xE4613C47);

    cc=cc << 1;
    sh1=sh1 << 1;
  }

}

//******************************************************************
byte parity(unsigned long li)
{
  byte po = 0;
  while(li != 0)
  {
    po++;
    li&= (li-1);
  }
  return (po & 1);
}

//******************************************************************
// interleave reorder the 162 data bits and and merge table with the sync vector
void interleave_sync(){
  int ii,ij,b2,bis,ip;
  ip=0;

  for (ii=0;ii<=255;ii++) {
    bis=1;
    ij=0;
    for (b2=0;b2 < 8 ;b2++) {
      if (ii & bis) ij= ij | (0x80 >> b2);
      bis=bis << 1;
    }
    if (ij < 162 ) {
      sym[ij]= SyncVec[ij] +2*symt[ip];
      ip++;
    }
  }
}

// This code by Yannick DEVOS XV4Y 2012

//******************************************************************
// Compute and initialize the sequence
void prepare_sequence() {

  encode_call();
  #ifdef SERIAL_OUT_INFO
  Serial.print("call: ");
  Serial.print(call);
  Serial.print(" ");
  Serial.print(n1,HEX);
  Serial.println(" ");
  #endif

  encode_locator();
  #ifdef SERIAL_OUT_INFO
  Serial.print("locator: ");
  Serial.print(locator);
  Serial.print(" ");
  Serial.print(m1 << 2,HEX);
  Serial.println(" ");
  for (bb=0;bb<=10;bb++){
    Serial.print(c[bb],HEX);
    Serial.print(",");
  }
  Serial.println("");
  #endif

  encode_conv();
  #ifdef SERIAL_OUT_INFO
  Serial.println("");
  for (bb=0;bb<162 ;bb++){
    Serial.print(symt[bb],DEC);
    Serial.print(".");
    if ( (bb+1) %32 == 0) Serial.println("");
  }
  Serial.println("");
  #endif

  interleave_sync();
  #ifdef SERIAL_OUT_INFO
  Serial.println("Channel symbols :");
  for (bb=0;bb<162 ;bb++){
    Serial.print(sym[bb],DEC);
    Serial.print(".");
    if ( (bb+1) %32 == 0) Serial.println("");
  }
  Serial.println("\nEnd of init.");
  #endif

};

//******************************************************************
// Function to send the test sequence
void send_test(char begin_sec) {
    if ((myClock.RTC_sec-(begin_sec+0))%30==0) {
      digitalWrite( PTT_key, LOW );
      digitalWrite( wsprPinA, LOW );
      digitalWrite( wsprPinB, LOW );
      #ifdef SERIAL_OUT_INFO
      Serial.println("* TX Low, Send 00 *");
      #endif
    }

    if ((myClock.RTC_sec-(begin_sec+6))%30==0) {
      digitalWrite( PTT_key, HIGH );
      digitalWrite( wsprPinA, LOW );
      digitalWrite( wsprPinB, LOW );
      #ifdef SERIAL_OUT_INFO
      Serial.println("* TX High, Send 00 *");
      #endif
    }

    if ((myClock.RTC_sec-(begin_sec+12))%30==0) {
      digitalWrite( PTT_key, HIGH );
      digitalWrite( wsprPinA, HIGH );
      digitalWrite( wsprPinB, LOW );
      #ifdef SERIAL_OUT_INFO
      Serial.println("* TX High, Send 01 *");
      #endif
    }

    if ((myClock.RTC_sec-(begin_sec+18))%30==0) {
      digitalWrite( PTT_key, HIGH );
      digitalWrite( wsprPinA, LOW );
      digitalWrite( wsprPinB, HIGH );
      #ifdef SERIAL_OUT_INFO
      Serial.println("* TX High, Send 10 *");
      #endif
    }
    
    if ((myClock.RTC_sec-(begin_sec+24))%30==0) {
      digitalWrite( PTT_key, HIGH );
      digitalWrite( wsprPinA, HIGH );
      digitalWrite( wsprPinB, HIGH );
      #ifdef SERIAL_OUT_INFO
      Serial.println("* TX High, Send 11 *");
      #endif
    }

};

  
//******************************************************************
// Function to send the sequence
void send_sequence() {
  for (bb = 0; bb < 162; bb++) {
    symbol = sym[bb];

    #ifdef SERIAL_OUT_INFO
    Serial.print(" ");
    Serial.print(symbol%10, DEC);
    #endif

    digitalWrite( wsprPinB, (symbol >> 1) );
    digitalWrite( LEDPinB, (symbol >> 1) );

    digitalWrite( wsprPinA, (symbol & 1) );
    digitalWrite( LEDPinA, (symbol & 1) );
    begin_chunk = myClock.RTC_chunk;
    while ( ((256+myClock.RTC_chunk-begin_chunk)%256)<175 ) {
      delay(0);
    };
  };
};


//******************************************************************
// Interruption for the RTC clock
interrupt(TIMER1_A0_VECTOR) Tic_Tac(void) {
  myClock.Inc_chunk();		      // Update chunks
};

Le Raspberry Pi avec deux fois plus de RAM pour le même prix

Ars Technica (http://arstechnica NULL.com/information-technology/2012/10/raspberry-pi-now-comes-with-double-ram-at-the-same-price/) nous informe que la Raspberry Fundation a annoncer que la quantité de mémoire RAM embarquée à bord du Raspberry Pi modèle B va être doublée pour passer de 256 Mo à 512 Mo. Pour une fois les acheteurs en liste d’attente vont être contents car ils vont tous bénéficier de la mise à jour.

Il semblerait que la demande des acheteurs était pour obtenir un “modèle C” plus puissant que l’actuel modèle B. Beaucoup d’utilisateurs souhaitent en faire un micro-ordinateur à part entière et faire tourner plusieurs applications dessus. La Raspberry Fundation a toutefois fait le choix de conserver le prix de 35 USD et d’améliorer le modèle actuel!

Les premiers FTDX-3000 de Yaesu livrés aux USA

James de WA2FAA nous informe qu’il a reçu son tout nouveau FTdx-3000 il y a quelques jours. Comme il possède aussi un FTdx-5000D, il s’est amusé à comparer les deux.

FTdx-3000 Dayton 2012 - Photo sur www.radiocronache.com (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/10/FTdx-3000_Dayton-2012 NULL.jpg)Selon lui, le récepteur est aussi bon dans l’un que dans l’autre (à l’oreille, sans mesure au banc d’essai). Sur son oscilloscope de contrôle, il a observé que le signal en émission était très propre. Il y a quelques détails qu’il aurait aimé voir implémenté différemment mais rien de rédhibitoire. Il parle par exemple de la fonction DNF (DSP Notch Filter) qui active un Notch numérique automatique. Il aurait aimé l’avoir sur le panneau de contrôle principal alors qu’apparemment il faut naviguer dans le menu du spectrum scope pour l’activer. En parlant de ce dernier, il trouve son affichage très bon (mais sans le comparer à celui du FTdx-5000 qui n’est pas un modèle du genre), son seul défaut est de se figer complètement quand on est en émission (pas de visualisation du signal transmis).

Il est disponible pour répondre aux questions (via le groupe Yahoo Yaesu_FTDX3000 (http://groups NULL.yahoo NULL.com/group/Yaesu_FTdx3000/))

Archives des chroniques hertziennes de XV4Y, ZL4YY