Archives par mot-clé : Analog Devices

Hermes Lite, une alternative économique au HPSDR

Hermes Lite KF7O (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2014/04/KF7O_hermeslite NULL.jpg)Le projet Hermes (http://openhpsdr NULL.org/wiki/index NULL.php?title=HERMES) est bien connu des amateurs de radio-logicielle (Software Define Radio). Il s’agit du transceiver a conversion numérique directe du projet HPSDR initié par la très active association TAPR (Tampa Amateur Packet Radio) qui a déjà tant fait pour notre hobby. Il regroupe les précédentes cartes Mercury, Pennylane, Metis et Excalibur sur une seule carte. Apache Labs qui produit les transceiver ANAN (http://xv4y NULL.radioclub NULL.asia/2012/12/17/sdr-de-apache-labs-tous-les-anan-10-anan-10-pa-et-hermes-expedies/) en propose d’ailleurs une version assemblée prêt à l’usage.

D’un point de vue technique ce design est irréprochable, mais cela à un coût qui le place hors de porté de nombreux amateurs cherchant juste un premier contact avec les SDR en HF. Steve KF7O a donc souhaité plancher sur une version très bas coût (la cible étant 150$) du frontal radio qui respecterait pourtant les normes de Hermes pour pouvoir utiliser les mêmes logiciels. Son projet Hermes-Lite utilise un convertisseur analogique-numérique/numérique-analogique (ADC/DAC) AD9866 qui lui donne une couverture de 0 à 36MHz mais pour une résolution limitée à 12 bits. Cela aura un impact négatif sur la gamme dynamique ainsi que la qualité du signal transmis mais le compromis reste acceptable pour beaucoup d’utilisations. La partie DSP est un dongle de développement FPGA BeMicro de chez Altera (http://www NULL.arrownac NULL.com/solutions/bemicro-sdk/).

Les premiers tests avec un prototype montrent que les performances sont plutôt bonnes comparées à celles d’une carte Hermes complète ou d’un SoftRock RXTX Ensemble. Steve manque toutefois de temps pour finaliser le projet et envisager une production à plus large échelle. Il recherche donc des bonnes volontés.

Prototype balise WSPR à DDS

Prototype kit Balise WSPR DDS XV4Y (http://xv4y NULL.radioclub NULL.asia/2012/12/21/prototype-balise-wspr-a-dds/100_3339/)Je suis plutôt satisfait de ma semaine! En grappillant quelques heures entre mes occupations professionnelles j’ai réussi à finaliser la mise au point de ma balise WSPR avec un DDS AD9850 (http://xv4y NULL.radioclub NULL.asia/boutique/?slug=product_info NULL.php&products_id=33). Le prototype fonctionne parfaitement et les séquences sont reçues à 100% sur mon ordinateur de contrôle. Les tests sur l’air se sont révélés décevant mais avec moins de 10mW sur 20 mètres, les conditions hivernales et aucune station proche il ne fallait pas non plus rêver. Je vais essayer de bricoler un petit PA d’appoint pour valider les tests.

Un des points sur lequel je bloquais était la quantité de mémoire très restreinte du MSP430G2553. Avec 512 octets on est vite à cours de place pour les variables, d’autant plus que la génération de la séquence de symboles WSPR en consomme plus de 350 à elle seule! Devoir contrôler calculer la séquence WSPR, contrôler le DDS, et l’écran graphique posait pas mal de stress sur le micro-contrôleur. J’ai du réécrire une partie du code et économiser les variables. Les méthodes de programmation moderne nous apprennent à favoriser la lisibilité et la réutilisabilité du code en découpant en fonction ou en créant des classes d’objets. C’est bien beau mais même si les compilateurs modernes optimisent tout cela très bien, cela consomme quand même beaucoup de mémoire. Pas grave sur un micro-ordinateur, mais vite contraignant sur un micro-contrôleur. Les purs et durs programment toujours en assembleur, pour ma part même après 20 ans en ayant débuté à 11 ans sur le microprocesseur 6803 de mon Alice 90 (http://alice NULL.system-cfg NULL.com/) monté à partir de pièces en vrac par F1GUM, la mayonnaise n’a jamais pris…

100_3341

Si maintenant le code fonctionne parfaitement et que le hardware rempli son rôle, il me reste maintenant à voir comment tout agencer pour en faire un kit facile à reproduire et à monter, et à écrire la documentation! Dernier point technique à valider, l’ajout de 4 boutons pour pouvoir le transformer facilement en VFO ou générateur de signal.

Librairie pour piloter un DDS AD9850 avec un LaunchPad/MSP430 ou un Arduino

[GTranslate]

Je partage avec vous un de mes premiers résultats dans la mise au point d’une balise WSPR autonome agile avec générateur de signal à DDS (http://xv4y NULL.radioclub NULL.asia/boutique/?slug=product_info NULL.php&products_id=33). Voici en effet une petite librairie qui simplifiera vos projets pour piloter un DDS de chez Analog Devices comme le AD9850. Vous pouvez aussi facilement concevoir un VFO pour vos montages personnel Bitx (http://xv4y NULL.radioclub NULL.asia/category/ham-radio/materiel/bitx/) ou Bingo.

Cette librairie est assez simple puisqu’elle comporte quelques fonctions pour initialiser le circuit et lui programmer une fréquence. Un paramètre permet de passer le circuit en mode Power Down et de le réveiller au cas où. Cela permet d’économiser de l’énergie et même de faire une forme de CW si votre DDS génère le signal directement.

La communication se fait en mode série via 4 broches d’un micro-contrôleur MSP430G2553 par exemple. Bien entendu il faut aussi fournir l’alimentation et la masse. Fait intéressant, l’AD9850 est très flexible et supporte 3,3V ou 5V pour son alimentation. Comme la librairie est aussi très simple et n’utilise qu’un mode de communication logicielle elle est virtuellement portable sur toutes les familles de micro-contrôleurs. Le code est écrit pour les environnement de développements basés sur Wiring comme par exemple Arduino ou Energia.

Vous pouvez télécharger la librairie complète sur la page de téléchargements (http://xv4y NULL.radioclub NULL.asia/boutique/docs/).

Le code pour le fichier de header AD9850.h

/*
 AD9850.h - Library for adding simple AD9850 control capabilities on MSP430

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

 ====
 Revision history :
 v1.00    2012-12-16
 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/>

 ///////////////////////////////// How to use the lib

 * Create an instance of the object with the pin for CLOCK, LOAD, DATA and RESET

 AD9850 myDDS (P1_5, P2_0, P2_1, P2_2);	 Example for LaunchPad

 * Initialize the AD9850 and do a reset

 myDDS.begin();
 myDDS.reset();

 */

// Core library
#if defined (__AVR_ATmega328P__) || defined(__AVR_ATmega2560__) // Arduino specific
#include "WProgram.h" // #include "Arduino.h" for Arduino 1.0
#elif defined(__32MX320F128H__) || defined(__32MX795F512L__) // chipKIT specific 
#include "WProgram.h"
#elif defined(__AVR_ATmega644P__) // Wiring specific
#include "Wiring.h"
#elif defined(__MSP430G2452__) || defined(__MSP430G2553__) || defined(__MSP430G2231__) // LaunchPad specific
#include "Energia.h"
#elif defined(MCU_STM32F103RB) || defined(MCU_STM32F103ZE) || defined(MCU_STM32F103CB) || defined(MCU_STM32F103RE) // Maple specific
#include "WProgram.h"	
#endif

// ensure this library description is only included once
#ifndef AD9850_h
#define AD9850_h

// library interface description
class AD9850
{
	// user-accessible "public" interface
public:
	AD9850(uint8_t pinClock, uint8_t pinLoad, uint8_t pinData, uint8_t pinReset);
	void begin();
	void reset();
	void SetFrequency(unsigned long frequency, boolean powerdown);	// Set the frequency and send PowerDown command if needed
	// A few private methods
private:
};

#endif

Le code pour le fichier de déclaration des routines AD9850.cpp

/*
 AD9850.h - Library for adding simple AD9850 control capabilities on MSP430

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

 Based on work by G7UVW

 ====
 Revision history :
 v1.00    2012-12-16
 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/>

 */

// include this library's description file
#include <AD9850.h>
//#include <legacymsp430.h>

#define DDS_CLOCK 125000000

// Constructor /////////////////////////////////////////////////////////////////
uint8_t _DDSpinClock;
uint8_t _DDSpinLoad;
uint8_t _DDSpinData;
uint8_t _DDSpinReset;

AD9850::AD9850(uint8_t pinClock, uint8_t pinLoad, uint8_t pinData, uint8_t pinReset)
{
	_DDSpinClock = pinClock;
	_DDSpinLoad = pinLoad;
	_DDSpinData = pinData;
	_DDSpinReset = pinReset;

};

// Methods /////////////////////////////////////////////////////////////////

void AD9850::begin()
{
    pinMode (_DDSpinClock, OUTPUT); 
    pinMode (_DDSpinLoad,  OUTPUT); 
    pinMode (_DDSpinData,  OUTPUT); 
    pinMode (_DDSpinReset, OUTPUT);

	digitalWrite(_DDSpinReset, LOW);
	digitalWrite(_DDSpinClock, LOW);
	digitalWrite(_DDSpinLoad, LOW);
	digitalWrite(_DDSpinData, LOW);		
}

void AD9850::reset()
{
	//reset sequence is:
	// CLOCK & LOAD = LOW
	//  Pulse RESET high for a few uS (use 5 uS here)
	//  Pulse CLOCK high for a few uS (use 5 uS here)
	//  Set DATA to ZERO and pulse LOAD for a few uS (use 5 uS here)

	// data sheet diagrams show only RESET and CLOCK being used to reset the device, but I see no output unless I also
	// toggle the LOAD line here.

    digitalWrite(_DDSpinClock, LOW);
    digitalWrite(_DDSpinLoad, LOW);

	digitalWrite(_DDSpinReset, LOW);
	delay(5);
	digitalWrite(_DDSpinReset, HIGH);  //pulse RESET
	delay(5);
	digitalWrite(_DDSpinReset, LOW);
	delay(5);

	digitalWrite(_DDSpinClock, LOW);
	delay(5);
	digitalWrite(_DDSpinClock, HIGH);  //pulse CLOCK
	delay(5);
	digitalWrite(_DDSpinClock, LOW);
	delay(5);
	digitalWrite(_DDSpinData, LOW);    //make sure DATA pin is LOW

	digitalWrite(_DDSpinLoad, LOW);
	delay(5);
	digitalWrite(_DDSpinLoad, HIGH);  //pulse LOAD
	delay(5);
	digitalWrite(_DDSpinLoad, LOW);
	// Chip is RESET now
}

void AD9850::SetFrequency(unsigned long frequency, boolean powerdown)
{
	unsigned long tuning_word = (frequency * 4294967296 ) / (DDS_CLOCK*10);  // As frequency is in tens of Hertz, we need to multiply by 10
	digitalWrite (_DDSpinLoad, LOW); 

	shiftOut(_DDSpinData, _DDSpinClock, LSBFIRST, tuning_word);
	shiftOut(_DDSpinData, _DDSpinClock, LSBFIRST, tuning_word >> 8);
	shiftOut(_DDSpinData, _DDSpinClock, LSBFIRST, tuning_word >> 16);
	shiftOut(_DDSpinData, _DDSpinClock, LSBFIRST, tuning_word >> 24);
	if (powerdown)
		shiftOut(_DDSpinData, _DDSpinClock, LSBFIRST, B00000100);	// If powerdown is true then send PowerDown command
	else
		shiftOut(_DDSpinData, _DDSpinClock, LSBFIRST, 0x0);

	digitalWrite (_DDSpinLoad, HIGH); 
}