Skip to content

8. Electronics design

At the begining, we have done the group assignement here. My part is the test equipement part.

Hero shot

1. Design

To design my board, I used KiCad and attended a course given by Nicolas Kaufmann. I was largely inspired by the quentorres board. The aim is to create a board which, by means of a button, will display the Morse code given by the user using LEDs. As a bonus, the deciphered code will be displayed in the computer console.

To create a board, first go to the “schematic”. In this blank page, you can add components with “1” and electrical inputs and outputs with “2”. Button 3 is used for labels, allowing us to link inputs and outputs together without having to draw wires.

First, I put in all the components I needed: a xiao RP2040, a button, 10 LEDs and 10 resistors. To add these components, once I’ve clicked on the “1”, I search for the name I need with the search bar and add it. Once all my components are in place, I click on “2” and search for 3.3V, 5V or GND depending on my needs. The necessary information can be found on the component datasheets. At the end, there must be no line ending in nothing.

Once this is done, you can move on to the PCB editor. Start by importing the components. Then scatter them and draw paths between them with the “4”. It’s advisable to leave a gap of at least 0.4mm between each channel so that drills can pass through. Connections are made by following the thin blue lines. The next step is to make the board support. Go to “5” and select “Edge.Cuts”. We then trace a shape that encompasses all the components.

Once the board has been made, export it as an SVG file like “6”, and put this export into mods.

So I chose to use the Xiao Seeed RP2040, with 10 LEDs and their resistors (limited by the number of pins available) and a button and its resistor. The circuit is created as follows:

This allows me to obtain this PNG image which I can transform using mods to driller it.

2. Drilling and soldering

I had a few problems using mods. When KiCad gave me an svg file, I actually needed the inverse of that file (which is transparent in black and inverse). There’s an inverse button, but when I used it the result was the back of the plate. I tried several methods, based on png and others, but they didn’t work very well. One solution is to use the “mill 2D PCB” and not the “mill 2D” for the Roland SRM-20 mill. You should also remember to activate the second branch at the end:

Once it’s been run through mods, the usable file is used to produce the circuit. I’ll then solder all the necessary components. To make sure the LEDs are the right way round, I’ll use an external power supply to run a small current through them (5V, 30mA).

3. Coding

For this part, I used extensively ChatGPT 3.5. First, I coded the part in charge of scrolling the LEDs to the right.

const int ledPins[] = {26, 27, 28, 29, 6, 7, 0, 1, 2, 4};
const int numLEDs = 10;

const int buttonPin = 3;
int buttonState = 0;

void setup() {
  for (int i = 0; i < numLEDs; i++) {
    pinMode(ledPins[i], OUTPUT);
  }
  pinMode(buttonPin, INPUT);
}

void loop() {

  buttonState = digitalRead(buttonPin); //read if the button in engage

  for (int i = numLEDs - 1; i > 0; i--) { // Take the LED one by one by searching their position on LedPins
    digitalWrite(ledPins[i], digitalRead(ledPins[i - 1])); // set the correct state
  }

  if(buttonState == 1) //if the button is engage, the first led is ON, otherwise the led is OFF
    digitalWrite(ledPins[0], 1);
  else
    digitalWrite(ledPins[0], 0);

  delay(100);
}

Then I coded the part that manages whether the press is long or short. I set a fast scrolling speed to make sure I had at least one square off between each point.

  delay(100);
  buttonState = digitalRead(buttonPin); // read if the button in engage
  if(buttonState == 1){
    buffer +=1; //count the time of engage button
    blank = 0; 
  }
  else // count the empty time (to know when a letter is done)
    blank+=1;

  if(buttonState == 0 && buffer != 0){ // if the button is pressed a sufficient ammont of time
    if(buffer == 1 || buffer == 2){ // simple click
      statusButton = 1;
      buffer = 0;
    }
    if(buttonState == 0 && buffer >2){ // long click
      statusButton = 1;
      buffer = 0;
      towTime = 0;
    }
  }

Then I do a function who convert the “.” ant the “-” in ASCII character.

char convertMorseCharToLetter(String morseChar) {
  // All the alphabet in morse
  const char* morseLetters[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", 
                                 "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", 
                                 "-.--", "--..", "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", 
                                 "---..", "----.", ""};

  for (int i = 0; i < 37; i++) { 
    if (morseChar == morseLetters[i]) { // If there is a character
      if (i == 36) { // If it's empty
        return ' '; 
      } else {
        return char('A' + i); // Return the code ASCII from 'A' to the index
      }
    }
  }
  return '?'; // If not found
}

There is the final result :

const int ledPins[] = {26, 27, 28, 29, 6, 7, 0, 1, 2, 4};
const int numLEDs = 10;

const int buttonPin = 3;
int buttonState = 0;
bool statusButton = false;
int buffer = 0;
int blank = 0;
int towTime = 2;

String letter = "";

void setup() {
  for (int i = 0; i < numLEDs; i++) {
    pinMode(ledPins[i], OUTPUT);
  }
  pinMode(buttonPin, INPUT);
}

char convertMorseCharToLetter(String morseChar) {
  // All the alphabet in morse
  const char* morseLetters[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", 
                                 "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", 
                                 "-.--", "--..", "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", 
                                 "---..", "----.", ""};

  for (int i = 0; i < 37; i++) { 
    if (morseChar == morseLetters[i]) { // If there is a character
      if (i == 36) { // If it's empty
        return ' '; 
      } else {
        return char('A' + i); // Return the code ASCII from 'A' to the index
      }
    }
  }
  return '?'; // If not found
}

void loop() {

  for (int i = numLEDs - 1; i > 0; i--) { // Take the LED one by one by searching their position on LedPins
    digitalWrite(ledPins[i], digitalRead(ledPins[i - 1])); // set the correct state
  }

  if(statusButton || towTime == 1 || towTime == 2){ // if the button is engage, the first led is ON, otherwise the led is OFF
    digitalWrite(ledPins[0], 1);
    statusButton = 0;
    towTime +=1;
  }
  else
    digitalWrite(ledPins[0], 0);

  delay(100);
  buttonState = digitalRead(buttonPin); // read if the button in engage
  if(buttonState == 1){
    buffer +=1;
    blank = 0;
  }
  else //compt the empty time 
    blank+=1;

  if(buttonState == 0 && buffer != 0){ // if the button is pressed a sufficient ammont of time
    if(buffer == 1 || buffer == 2){ // simple click
      statusButton = 1;
      buffer = 0;
      letter += String(".");
    }
    if(buttonState == 0 && buffer >2){ // long click
      statusButton = 1;
      buffer = 0;
      towTime = 0;
      letter += String("-");
    }
  }

  if(blank > 15){
    blank = 0;
    Serial.print(convertMorseCharToLetter(letter));
    letter = "";
  } 
}

4. The files

Here you can find the Ardwino file

Here you can find the png contour file

Here you can find the png board file

Here you can find the rml board file

Here you can find the rml contour file