User Tools

Site Tools


project:weathersonde:eeprom_mgmt

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

connection note

This post was send by email, if You have difficulty to read/write eeprom, try this I've managed to solve it. Please let my now if You find any incorrectness.

It turned to be some weird voltage translation stuff. When the onboard CPU is in reset, the SCK and MOSI lines are held low (0V) by a relatively low impedance (about 250R, but the I-V curve is nonlinear), and the CS is held high (2.85V) by low impedance (about 300R, I-V curve non-linear). The MISO line is truly floating or connected to very highimpedance. I've used 100R series resistors on the SCK and MOSI lines. This gives me around 3V on the EEPROM pins when the Arduino is driving this lines high to 5V. When the Arduino drives this lines low to 0V, I get 0V on the other side as well. The CS is more problematic, because a low enough series resistor to make the Arduino drive it low effectively will make the voltage too high when the Arduino drives it to 5V. Therefore, I've connected this line to the collector of an NPN transistor. The emitter is grounded and the base is conected through 1k to the CS pin of the Arduino. I drive the CS pin on the Arduino in an inverted fashion. Thus, the NPN transistor pulls the EEPROM CS to ground when CS is active and the rest of the time the EEPROM CS is pulled high by the onboard CPU. With this setup I'm starting to get data out of the EEPROM.

Regards,

Daniel.

Code

/*
 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.txt · Last modified: 2018/10/01 13:48 by pinky