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