User Tools

Site Tools


project:weathersonde:eeprom_mgmt

This is an old revision of the document!


Arduino sketch for control via SPI

I've recovered two weather sondes with my friend, and played with them. Googled, and the result is a simple program run on an Arduino (I had a mega2560 lying around…).

The program needs an LCD display (2×16 or 2×20 characters), an Arduino (can be transferred easily for smaller ones also), 4 buttons, and a Vaisala SGP weather sonde.

Usage: connect the sonde, power up the circuit with the sonde attached to the Arduino.

Plus button: increases frequency 10 KHz Minus button: decreases frequency 10 KHz PWR mode button: changes the transmitter state Save button: saves the changes to the sonde EEPROM.

Thanks, and have a nice day, Peter from Budapest, Hungary

/*
 Connect an LCD display to the Arduino. Connect the Vaisala RS92 to the SPI port, connect the SS pin to a digital output.
 Pins are user configurable! Don't forget, that the project can be run on any types of Arduino. I had a Mega 2560 lying around,
 but the program is very simple to run also on an Arduino UNO. (pins needed to be changed).
 A standard 2x16 character LCD is used for display.
 
 The program reads the frequency and the transmitter status from the EEPROM, and lets the user to modify them. 
 
 Button 1: plus frequency, Arduino PIN 2
 Button 2: minus frequency, Arduino PIN 3
 Button 3: change transmitter state, Arduino PIN 4
 Button 4: save to Vaisala RS92, Arduino PIN 5
 
 PIN connections of the Vaisala service connector (edge connector, PIN1 is downside left, when the Vaisala is standing on the battery side).
 Source: https://brmlab.cz/project/weathersonde/hw

 1 - GND, connect to Arduino GND
 2 - VCC, connect to Arduino VCC input. Maximum allowed: 12V
 3 - 7: used for the original Vaisala launch station, not used in this project 
 8: EEPROM Chip Select, connect to Arduino PIN 29.
 9: EEPROM MOSI, connect to Arduino SPI header MOSI pin
 10: EEPROM CLOCK, connect to Arduino SPI header SCK pin
 11: EEPROM MISO, connect to Arduino SPI header MISO pin
 12: RS92 microprocessor /RESET. Connect it to GND, to prevent the Vaisala CPU from starting, during EEPROM manipulation.
 
 LCD display: in our example, connected to PIN 22 - 27 of Arduino. Feel free to modify the pinout!
 
 You may freely copy or modify this program! Have fun with your new meteorological sonde! Use SDRSharp and SondeMonitor and a cheap Realtek DVB-T stick for reception.
 Don't forget to alter the frequency below 406 MHz, and lower the TX power if you plan to use the sonde as an outside weather station.
 
 (c) Peter Thiering 2015, thieringpeti@gmail.com
 */

// include the library code:
#include <LiquidCrystal.h>
#include <SPI.h>

const int VAISALA_CONFIG = 0x70;// The Vaisala configuration BLOB starts at 0x7000
const int VAISALA_FREQ1 = 0x02;// Offset of the frequency. (two bytes)
const int VAISALA_FREQ2 = 0x03;

const int VAISALA_STATUS = 0x7A; // The Vaisala transmitter status BLOB starts at 0x7A00
const int VAISALA_PWR = 0x04; // offset of the status register for the transmitter. Values 0-3 are allowed. (LO,MID,HI,PWRSAVE)

// eeprom commands
#define WREN  6
#define WRDI  4
#define RDSR  5
#define WRSR  1
#define READ  3
#define WRITE 2

// buttons

#define PLUS 2
#define MINUS 3
#define TXPWR 4
#define SAVE 5

#define CSPin 29
byte data; // transmitter data register
byte f1; // frequency register 1
byte f2; // frequency register 2
unsigned long freq;
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(22, 23, 24, 25, 26, 27);

void setup() {
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.

  // initalize the  data ready and chip select pins:
  pinMode(CSPin, OUTPUT);
  pinMode(53,OUTPUT);
  pinMode(52,OUTPUT);
  pinMode(51,OUTPUT);
  pinMode(50,INPUT);
  pinMode(PLUS, INPUT);
  pinMode(MINUS, INPUT);
  pinMode(TXPWR,INPUT);
  pinMode(SAVE,INPUT);

  digitalWrite(PLUS, HIGH);
  digitalWrite(MINUS, HIGH);
  digitalWrite(TXPWR,HIGH);
  digitalWrite(SAVE,HIGH);
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  SPI.begin();
  readData();
  displayData();
}

void readData(void)
{
  digitalWrite(CSPin, LOW);
  // send the device the register you want to read:
  SPI.transfer(READ);
  SPI.transfer(VAISALA_STATUS);
  SPI.transfer(VAISALA_PWR);
  data = SPI.transfer(0x00);
  // send a value of 0 to read the first byte returned:
  digitalWrite(CSPin,HIGH);

  // read freq

  digitalWrite(CSPin,LOW);
  SPI.transfer(READ);
  SPI.transfer(VAISALA_CONFIG);
  SPI.transfer(VAISALA_FREQ1);
  f1 = SPI.transfer(0x00);
  f2 = SPI.transfer(0x00);

  digitalWrite(CSPin,HIGH);
}

void displayData(void)
{
  lcd.setCursor(0, 1);
  lcd.print("FREQ: 40");
  lcd.setCursor(13, 1);
  lcd.print("KHz");
  lcd.setCursor(0,0);
  if (data == 0x02)  lcd.print("TX High PWR     ");
  if (data == 0x01) lcd.print("TX Mid PWR      ");
  if (data == 0x00) lcd.print("TX Low PWR      ");
  if (data == 0x03) lcd.print("TX Energy Saving");
  if (data > 0x03) lcd.print("bad TX data     ");

  freq = f1*10 + f2 * 2560 + 400000;
  lcd.setCursor(6, 1);
  lcd.print(freq);
}

void scanButtons(void)
{
  int plusbutton = !digitalRead(PLUS);
  int minusbutton = !digitalRead(MINUS);
  int pwrbutton = !digitalRead(TXPWR);
  int savebutton = !digitalRead(SAVE);

  while ((plusbutton || minusbutton || pwrbutton || savebutton) == 0)
  {
    plusbutton = !digitalRead(PLUS);
    minusbutton = !digitalRead(MINUS);
    pwrbutton = !digitalRead(TXPWR);
    savebutton = !digitalRead(SAVE); 
  }

  if (plusbutton)
  {
    if (f1 == 0xff) 
    {
      if (f2 != 0xff) {
        f2 += 1; 
        f1 = 0;
      }
    }
    else
    { 
      f1 += 1; 
    }
  }

  if (minusbutton)
  {
    if (f1 == 0) 
    {
      if (f2 != 0) {
        f2 -= 1; 
        f1 == 0xFF;
      }
    } 
    else if (f1 != 0)
    { 
      f1 -= 1; 
    }
  }

  if (pwrbutton)
  {
    switch (data)
    {
    case 0: 
      data = 1; 
      break;
    case 1: 
      data = 2; 
      break;
    case 2: 
      data = 3; 
      break;
    case 3: 
      data = 0; 
      break; 
    default: 
      data = 3; 
      break;
    }
  }

  lcd.setCursor(19,0);
  lcd.print("*");

  if (savebutton)
  {
    saveData();
    lcd.setCursor(19,0);
    lcd.print("S");
  }

  displayData();

  while ((plusbutton || minusbutton || pwrbutton || savebutton) != 0)
  {
    plusbutton = !digitalRead(PLUS);
    minusbutton = !digitalRead(MINUS);
    pwrbutton = !digitalRead(TXPWR);
    savebutton = !digitalRead(SAVE); 
  }
}

void saveData(void)
{
  
    digitalWrite(CSPin, LOW);
    SPI.transfer(WRSR);
    SPI.transfer(0x02);
    digitalWrite(CSPin,HIGH);
   
    digitalWrite(CSPin, LOW);
    SPI.transfer(WREN);
    digitalWrite(CSPin,HIGH);
    delay(10);
    digitalWrite(CSPin, LOW);
  // send the device the register you want to read:
  SPI.transfer(WRITE);
  SPI.transfer(VAISALA_STATUS);
  SPI.transfer(VAISALA_PWR);
  SPI.transfer(data);
  // send a value of 0 to read the first byte returned:
  digitalWrite(CSPin,HIGH);

  delay(100);
  // write freq

    digitalWrite(CSPin, LOW);
    SPI.transfer(WRSR);
    SPI.transfer(0x02);
    digitalWrite(CSPin,HIGH);

    digitalWrite(CSPin, LOW);
    SPI.transfer(WREN);
    digitalWrite(CSPin,HIGH);
    delay(100);
    digitalWrite(CSPin,LOW);
  SPI.transfer(WRITE);
  SPI.transfer(VAISALA_CONFIG);
  SPI.transfer(VAISALA_FREQ1);
  SPI.transfer(f1);
  digitalWrite(CSPin,HIGH);
    delay(100);
    digitalWrite(CSPin, LOW);
  SPI.transfer(WRSR);
  SPI.transfer(0x02);
   digitalWrite(CSPin,HIGH);
  digitalWrite(CSPin, LOW);
  SPI.transfer(WREN);
   digitalWrite(CSPin,HIGH);
   delay(100);
  digitalWrite(CSPin,LOW);
  SPI.transfer(WRITE);
  SPI.transfer(VAISALA_CONFIG);
  SPI.transfer(VAISALA_FREQ2);
  SPI.transfer(f2);
  digitalWrite(CSPin,HIGH);
}

void loop() {
  scanButtons();
  delay(20);
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):

  // print the number of seconds since reset:
}
project/weathersonde/eeprom_mgmt.1483467312.txt.gz · Last modified: 2017/01/03 18:15 by pinky