This week, I focused on designing, fabricating, and assembling a custom PCB. I used KiCad for schematic and PCB design, then fabricated the board using milling and laser etching, and finally assembled and tested it.
Learning Objectives
Select and use software for circuit board design
Demonstrate workflows used in circuit board design
Assignments
Group Assignments
probe an input device's analog levels and digital signals
The rotary encoder generates (when rotating) two square waves on pins A (CLK) and B (DT) with 90° out of phase as shown in the figure below:
Encoder: Output Waveform
Since the normal state of pin A (CLK) and pin B (DT) are logic high we've to detect falling (transition from high to low) of one of them, here pin A is used to detect the movement of the rotary encoder in both directions (falling of pin A signal). Direction of rotation can be detected by knowing the status of pin B, if pin B is logic high this means the direction of rotation is clockwise (CW), and if pin B is logic low this means the direction of rotation is counter clockwise (CCW).
SAMD 21
Design Rules
Designing the Microcontroller Board
I decided to try something which involved buttons, sliders and enncoders for my final project - Symphoni The Record Player. But after seeing the class, I was amused by the capacitive touch and its capabilities. Therefore I decided my sensors for the week - Capacitive Touch Slider and Rotary Encoder.
I decided to use a 5 Capacitive Pad slider with a rotary encoder. And I decided to explore a new microcontroller - SAMD21 E17A.
Design Rules
I refered to some previous works of students who used capacitive touch and SAMD21
I refered to these documentations and studied about different types of Capacitive touch sensors and how they work. I studied about how these sensors work, and then Saheen told me that the board I chose, already has QTouch capibilities
I studied about how QTouch works on SAMD21 E17, the SAMD21 has specific pins called PTC pins to control
The QTouch® Peripheral Touch Controller (PTC) offers built-in hardware for capacitive touch measurement on sensors that function as buttons, sliders, and wheels. The PTC has been designed to perform capacitive touch acquisition on sensors independently from the CPU, resulting in low CPU utilization and reduced power consumption.
The WS2812B uses 5V but my MCU uses 3.3 V logic level, therefore I needed the 5V output. So I had to make a logic level shifter. So I learned more about Logic Level Shifter.
After going back to the documentation, I realised that I had missed out on some essential connections on the board.
TouchNav SAMD21
The device has several different power supply pins:
VDDIO: Powers I/O lines, OSC8M and XOSC. Voltage is 1.62V to 3.63V.
VDDIN: Powers I/O lines and the internal regulator. Voltage is 1.62V to 3.63V.
VDDANA: Powers I/O lines and the ADC, AC, DAC, PTC, OSCULP32K, OSC32K, XOSC32K. Voltage is 1.62V
to 3.63V.
VDDCORE: Internal regulated voltage output. Powers the core, memories, peripherals, FDPLL96M, and
DFLL48M. Voltage is 1.2V.
The same voltage must be applied to both VDDIN, VDDIO and VDDANA. This common voltage is referred to as VDD
in the datasheet.
The ground pins, GND, are common to VDDCORE, VDDIO and VDDIN. The ground pin for VDDANA is GNDANA
SAMD21 Recommended Power connectionVDD ConnectionsFinal SchematicTouchNav Schematic PDFSAMD21 DocumentationHero ShotsHero ShotsHero Shots
Programing TouchNav(SAMD21 Board)
TouchNav SAMD21 ComponentsTouchNav Serial Debug Pins Bootloader ProgrammingSaheen's SAMD ProgrammerProgramming SetupAdding the FAB SAMD Board to Arduino
To program the SAMD21 Board using Arduino IDE, we need to add the FAB SAMD Board to the Board Manager
Adding BoardSelecting SAMD BoardTouchNav Serial Debug Pins Saheen's SAMD Programmer
Programming SetupSerial Debug Connection
Blink
// the setup function runs once when you press reset or power the board
void setup() {
// initialize builtin LED at pin 7 as an output.
pinMode(7, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(7, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(7, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
SAMD21 Serial Demo
void setup() {
SerialUSB.begin(115200);
}
#define max_buffer 25
void loop() {
static char chr;
static char buffer[max_buffer] = { 0 };
static int index;
if (SerialUSB.available()) {
chr = SerialUSB.read();
SerialUSB.print("hello.D21E.echo: you typed \"");
buffer[index++] = chr;
if (index == (max_buffer - 1))
index = 0;
SerialUSB.print(buffer);
SerialUSB.println("\"");
}
}
Rotary Encoder
// Rotary Encoder Inputs
#define CLK 9
#define DT 8
#define SW 10
int counter = 0;
int currentStateCLK;
int lastStateCLK;
String currentDir ="";
unsigned long lastButtonPress = 0;
void setup() {
// Set encoder pins as inputs
pinMode(CLK,INPUT);
pinMode(DT,INPUT);
pinMode(SW, INPUT_PULLUP);
// Setup Serial Monitor
SerialUSB.begin(9600);
// Read the initial state of CLK
lastStateCLK = digitalRead(CLK);
}
void loop() {
// Read the current state of CLK
currentStateCLK = digitalRead(CLK);
// If last and current state of CLK are different, then pulse occurred
// React to only 1 state change to avoid double count
if (currentStateCLK != lastStateCLK && currentStateCLK == 1){
// If the DT state is different than the CLK state then
// the encoder is rotating CCW so decrement
if (digitalRead(DT) != currentStateCLK) {
counter ++;
currentDir ="CW";
} else {
// Encoder is rotating CW so increment
counter --;
currentDir ="CCW";
}
SerialUSB.print("Direction: ");
SerialUSB.print(currentDir);
SerialUSB.print(" | Counter: ");
SerialUSB.println(counter);
}
// Remember last CLK state
lastStateCLK = currentStateCLK;
// Read the button state
int btnState = digitalRead(SW);
//If we detect LOW signal, button is pressed
if (btnState == LOW) {
//if 50ms have passed since last LOW pulse, it means that the
//button has been pressed, released and pressed again
if (millis() - lastButtonPress > 50) {
SerialUSB.println("Button pressed!");
}
// Remember last button press event
lastButtonPress = millis();
}}