Thursday, 18 August 2016

BBC Micro:bit calls CQ CQ...

There is a new module available for the BBC micro:bit in the MicroPython programming language. This is a speech generating module.

The results are crude, unless you very carefully adjust the message content and speech settings. But it works out of the box.

Here is a short program to call CQ for myself, M6KWH.

Code

# Call CQ M6KWH
from microbit import *
import speech

# init pin0 to 0 to define a level and stop "hum"
pin0.write_digital(0)

message = "C Q! C Q! C Q!   M 6 K W H! calling C Q!"
while True:
    # flash arrow W
    display.show(Image.ARROW_W)
    sleep(500)
    display.clear()
    sleep(500)
    
    # if A pressed, say greetings
    if button_a.was_pressed():
        speech.say(message, speed=80)
        sleep(1000)

Wednesday, 17 August 2016

433MHz control of room lighting

The Energenie sockets that are very low cost on Amazon, are controlled by a push button hand-held controller. It outputs codes over a 433.92MHz RF signal, which the sockets receive and respond to.

Each socket has a different code, one for ON and one for OFF.

RX & TX

There are some very low cost 433.92MHz transmitters and receivers on the market (below £2 the pair!). Using the receiver and some Arduino software the codes for your personal sockets can be read from the hand-held controller. Once you know these, a second Arduino program can be used to send these code out using the transmitter, and this will control the sockets.

The software for all this is in a library called "RCSwitch.h" downloadable here. The examples given with this library show how to use it.

Screen Shot 2016 08 17 at 10 41 11

These are the Energenie sockets and their controller. Each socket has to initialised to match a code from the controller, but when this is done the sockets can be controlled from the Arduino and connected transmitter.

Screen Shot 2016 08 17 at 10 51 12

The receiver is on the right and the transmitter to the left. Each has three connections (the OUTput of the receiver is on two connected pins). The receiver is connected to +5V, pin 2 (interrupt 0) and GND when you run the code reading sketch (see RCSwitch Examples). The transmitter is connected to +5V, Arduino pin 10 and GND. The sketch below allows you to type 1/2, 3/4, 5/6 into the Arduino Serial Monitor window and to switch ON or OFF three of the sockets (the code could easily be extended to cover the four sockets, and the ability to switch ON/OFF all the sockets at once. The codes below are for the sockets I bought, you will have to read and substitute your own codes.

Code to read remote codes

// RX_find_code_1
// detects remote RF signals and IDs LOW, HIGH and length
// start program, then push a button on the remote
// reset to re-run the program

// LED pin, RX input pin
 #define LEDPIN 13
 #define RXPIN A0

 //Create an array to store the data
 const int dataSize = 500;
 byte storedData[dataSize];

 // upper and lower thresholds
 const unsigned int upperThreshold = 100;
 const unsigned int lowerThreshold = 80;
 
// maximum length of the signal, length of signal
 int maxSignalLength = 255;
 int dataCounter = 0;

 // start time, end time, read time
 unsigned long startTime = 0;
 unsigned long endTime = 0;
 unsigned long signalDuration = 0;
 
 void setup(){
  Serial.begin(9600);
  pinMode(LEDPIN, OUTPUT);
  
  /* The following code will only run ONCE --------------
  ---Press the reset button on the Arduino to run again-- */
  
  //Wait here until a LOW signal is received
  while(analogRead(RXPIN) < 1) {
      startTime = micros();  //Update start time with every cycle.
  }
  digitalWrite(LEDPIN, HIGH);  //Turn LED ON
  
  //Read and store the rest of the signal into the storedData array
  for(int i = 0; i < dataSize; i = i+2) {
    
    //Identify the length of the LOW signal---------------LOW
    dataCounter = 0; //reset the counter
    while(analogRead(RXPIN) > upperThreshold && dataCounter < maxSignalLength) {
      dataCounter++;
    }
    storedData[i] = dataCounter;
    
    //Identify the length of the HIGH signal---------------HIGH
    dataCounter = 0;//reset the counter
    while(analogRead(RXPIN) < lowerThreshold && dataCounter < maxSignalLength){
      dataCounter++;
    }
    storedData[i+1] = dataCounter;
    
    /* Any readings between the two threshold values will be ignored.
     *
     * The LOW or HIGH signal length must be less than the variable "maxSignalLength"
     * otherwise it will be truncated.
     *
     * All of the HIGH signals and LOW signals combined must not exceed the variable "dataSize"
     * otherwise it will be truncated.
     *
     * The maximum number of signals is 1700 (memory limit)
     * If you try to extend this variable to a higher number than 1700
     * then the Arduino will freeze up and sketch will not work.*/
  }


  //Record the end time of the read period.
  endTime = micros();
  signalDuration = endTime - startTime;

  //Turn LED OFF
  digitalWrite(LEDPIN, LOW);
  
  //Send report to the Serial Monitor
  Serial.println("=====================");
  Serial.print("Read duration: ");
  Serial.print(signalDuration);
  Serial.println(" us");
  Serial.println("=====================");
  Serial.println("LOW, HIGH");
  delay(20);
  for(int i = 0; i < dataSize; i = i+2) {
    Serial.print(storedData[i]);
    Serial.print(", ");
    Serial.println(storedData[i+1]);
    delay(20);
  }
 }

 void loop(){
   //Do nothing here, press reset to re-run the program
 }
Code to transmit the codes

/*
 Example for my own codes, yours may be different
*/
 
#include 
 
// constructor for mySwitch object
RCSwitch mySwitch = RCSwitch();

byte inByte = 0;

void setup() {
 
 Serial.begin(9600);
 
 // Transmitter is connected to Arduino Pin 10
 mySwitch.enableTransmit(10);
 
// Optional set pulse length.
 // mySwitch.setPulseLength(320);
 
 // Optional set protocol (default is 1, will work for most outlets)
 // mySwitch.setProtocol(2);
 
 // Optional set number of transmission repetitions.
  mySwitch.setRepeatTransmit(4);
 
 Serial.println("Ready"); // Ready to receive commands
}
 
void loop() {
 /* Switch using decimal code */
 if(Serial.available() > 0) { // A byte is ready to receive
   inByte = Serial.read();

   if(inByte == '1') { // byte is '1'
     mySwitch.send(14237327, 24);
     Serial.println("1 ON");
   }
   else if(inByte == '2') { // byte is '2'
     mySwitch.send(14237326, 24);
     Serial.println("1 OFF");
   }
   else if(inByte == '3') { // byte is '3'
     mySwitch.send(14237319, 24);
     Serial.println("2 ON");
   }
   else if(inByte == '4') { // byte is '4'
     mySwitch.send(14237318, 24);
     Serial.println("2 OFF");
   }
   else if(inByte == '5') { // byte is '5'
     mySwitch.send(14237323, 24);
     Serial.println("3 ON");
   }
   else if(inByte == '6') { // byte is '6'
     mySwitch.send(14237322, 24);
     Serial.println("3 OFF");
   }
 }
}
My future target is to add a speech recognition board from Audeme to the Arduino UNO and control my lighting by voice!

Thursday, 11 August 2016

Morse Code Trainer

One thing about morse code is you need repetitive training. No better way to learn and improve your reception. So here's a thing - a MicroPython program running on the BBC micro:bbit that generates random morse letters and sounds for you to train by.

IMG 0146

The connections are simple, pin'0' and GND go to an active piezo buzzer.

Code

The code is self explanatory, for those that know Python. It was written in the "Mu" code editor which has been specifically written to support the micro:bit on all platforms.

from microbit import *
import random

# 'constants' for delays all derived from dot length
dotlength = 250
dashlength = dotlength * 3
interelement = dotlength
interletter = dotlength * 2

# images for displaying dots and dashes

dot_img = Image('00000:00000:00900:00000:00000:')
dash_img = Image('00000:00000:09990:00000:00000:')

letter = ("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z")

# Dictionary
morse = {
    "A":".-",
    "B":"-...",
    "C":"-.-.",
    "D":"-..",
    "E":".",
    "F":"..-.",
    "G":"--.",
    "H":"....",
    "I":"..",
    "J":".---",
    "K":"-.-",
    "L":".-..",
    "M":"--",
    "N":"-.",
    "O":"---",
    "P":".--.",
    "Q":"--.-",
    "R":".-.",
    "S":"...",
    "T":"-",
    "U":"..-",
    "V":"...-",
    "W":".--",
    "X":"-..-",
    "Y":"-.--",
    "Z":"--.."
}

# function to convert string to pattern of dots and spaces
def EncodeMorse(message):
    m = message.upper()
    enc = ""
    for c in m:
        enc = enc + morse.get(c," ")
        if morse.get(c," ") != " ":
            enc = enc + " "
    return enc
    
# function to flash out a Morse pattern on the matrix
def FlashMorse(pattern):
   for c in pattern:
       if c == ".":
           display.show(dot_img)
           pin0.write_digital(1)
           sleep(dotlength)
           display.clear()
           pin0.write_digital(0)
           sleep(interelement)
       elif c=="-":
           display.show(dash_img)
           pin0.write_digital(1)
           sleep(dashlength)
           display.clear()
           pin0.write_digital(0)
           sleep(interelement)
       elif c==" ":
           sleep(interletter)
   return

# helper function to encode and flash in one go
def MorseCode(message):
    m = EncodeMorse(message)
    print(m)
    FlashMorse(m)
    return

while True:
    message = random.choice(letter)
    MorseCode(message)
    sleep(2000)


    
    

Tuesday, 9 August 2016

Micro:bit Traffic Lights

A simple, but fun, application of the BBC Micro:bit is to build a set of pedestrian traffic lights. You push the button, the lights cycle to red, it goes pip-pip-pip then the lights cycle back to green.

IMG 0143

Pin 0 goes to the active piezo buzzer, pins 13, 14, 15 are the G, Y, R LEDs and the "cross" switch is on pin 16. The LEDs have series 330R resistors (the current must be limited to less than 5mA for the micro:bit), and the switch has a pull up resistor of 10k to 3V.

Code

# Traffic lights
# pins 330R-LED-GND: 13 green, 14 yellow, 15 red, 16 switch(10k pull-up, active LOW)

# import the micropython library
from microbit import *

# set period of pin 0 pwm output
pin0.set_analog_period(400)
pin0.write_analog(0)

while True:
    # green on
    pin13.write_digital(1)
    display.show("G")
    
    # wait for switch
    if pin16.read_digital() != 1:
        
        # green off, yellow on
        pin13.write_digital(0)
        pin14.write_digital(1)
        display.show("Y")
        sleep(2000)
        
        # yellow off, red on, pip-pip-pip
        pin14.write_digital(0)
        pin15.write_digital(1)
        display.show("R")
        pin0.write_analog(200)
        sleep(8000)
        
        # yellow on, red remains on, pip off
        pin14.write_digital(1)
        display.show("Y")
        pin0.write_analog(0)
        sleep(2000)
        
        # red & yellow off
        pin14.write_digital(0)
        pin15.write_digital(0)

# loop
Press the button to cross the road