Hardware 101

Welcome to the UW Midnight Sun Hardware team! Joining the team is definitely a rewarding experience, but requires time and effort in order to learn and apply many hardware engineering concepts required to building a solar car! This Hardware 101 does not require a strong knowledge in electrical circuits, but does require patience, and a desire to learn and understand how circuits work. So no matter your knowledge level, you can finish this project and learn a lot on the way.

Since it may be a bit overwhelming to jump straight into an active project for the car, it's best to start things off at a much simpler scale in order to properly grasp the design process for a board, as well as get used to the software tools for development and testing. We will be accomplishing these goals through a tutorial board that will have you ready for working on active and future board for the car.

General Description

The purpose of this exercise is to get you familiar with the following:

  • Using Altium for schematic and PCB layout
  • Using Jira for task tracking and Git for version control 
  • Reading datasheets and creating basic circuits 

You will be doing this through an introductory project that is the basis of a real Midnight Sun board design used in the car.

Problem Statement:

  • Control LEDs with corresponding buttons through a microcontroller  → Similar to driver controls where we use buttons to control various functions of the car 
  • Adjust the brightness of LEDs to be proportional to a potentiometer → Similar to reading any analog sensor data and doing something with it 

IO’s:

  • 2 buttons (digital input)
  • 1 potentiometer (analog input)
  • 2 LEDs (digital output)

Requirements:

  • Buttons need to be properly debounced 
  • Use our controller board (STM32F072CBT6 on board, Schematic is called Controller Board Interface) 
    • Use appropriate GPIOs
    • Note that with the Controller Board, you should only have the Mezannine connector in your schematic and not the microcontroller itself! 


Starting the Project

Before we get into making any circuits or PCBs, let's first make sure we understand what we need to accomplish. By reading the above description, we know we need to design a PCB that has two buttons, a potentiometer, and two LEDs. We also know that the functionality of the board is as follows: when a button is pressed, a corresponding LED should turn on. Great! 

But this sounds so simple... the first google search can tell us exactly how to do wire a circuit that does this:

Image result for circuit with button and led

It's true, the underlying concept of turning on an LED with a button is simple, but we have added some requirements to this project in order to make it more applicable to our design process and to incorporate ideas that will help with design of future boards. If you remember under the requirements heading, it said "Buttons need to be debounced", and "Use our microcontroller (STM32F072CBT6)..." - Let's try to understand these requirements one by one while building a block diagram for what our circuit will look like (This block diagram will be useful when we begin to use Altium).


Creating the Block Diagram

So far we know our inputs and outputs. For now, assume that one end of the button is connected to 3.3 V, and the other end should be connected somehow to our microcontroller. The cathode (negative) end of the LEDs will be connected to ground. If we put them on a block diagram we have something that looks like:


Let's now use our requirements to complete this circuit.

Requirement 1: Debouncing buttons

A quick google search on what button debouncing is can give you a good understanding of the theory behind why we need to 'debounce' buttons and switches. Generally, a button (the one we use for this project) is comprised of two metal contacts that complete a circuit when pressed. Unfortunately, this metal contact created by a human press is never perfect, and can result in the signal toggling between low and high a few times before settling down, which if not treated can result in undesirable behaviour from your circuit. This 'unwanted toggling' looks something like:

Do you see the first chunk of the signal? It goes high (on) and low (off) multiple times before stabilizing at the on position. Now, our car uses a push-to-start button; imagine that effect happening on a button like that! It's definitely undesirable, and our goal in this tutorial is to show you a couple of ways to debounce a button and obtain a clean signal from a button press. One way to reduce the effect of the button bouncing of course, is to implement de-bouncing in firmware, where we can wait a certain time after the first state change before sampling again to avoid sampling the input during the time when it bounces. While this should work in the majority of the cases, you will see that it's fairly simple to implement a better version in hardware that will not use any processor resources.


Method 1: Low Pass Filter (LPF)

Image result for rc lpf

Before we understand what a low pass filter does, let's make sure we understand the concept of AC voltage/current. If you do not know the difference between the two, this link should help you. Now, notice what the unwanted voltage ripple looks like when the button is pressed: it's oscillating, which we can think of as AC voltage.

Another thing we need to understand is what a Capacitor is, and how it behaves under DC and AC. In essence, a capacitor behaves as an open circuit under DC operation, and a short circuit under high frequency AC operation (with varying degrees over a frequency range). Since our unwanted ripple voltage resembles an AC voltage at some frequency, we can use the capacitor's properties to try and mitigate this noise. 

But how does this circuit shown above get rid of high frequency noise? Well, think about it - if the input signal is DC, a capacitor behaves as an open circuit, and so the bottom branch (which has the cap) will render obsolete, and Vin = Vout. However, if the input signal is a high frequency AC, the capacitor behaves as a short circuit, and now we've created a short circuit to ground, so Vout = 0. We can characterize this behaviour using a 'frequency response' (gain vs frequency) plot, or more commonly known as a Bode plot. 

Image result for rc lpf

Another property of a capacitor is that is takes some time to charge up under AC operation (this time depends on the value of the capacitance); and we can use this to create a 'delay' between the button press, and the signal output. This delay can also be characterized using an 'impulse response' plot (voltage vs time):

Image result for rc lpf impulse response

Generally, for buttons, the provided datasheet (example) for the button will include a 'bounce time'. This is the time that the button will take in order to produce a clean, stable signal when pressed (after the noise settles). In the case of the buttons we want to use for this tutorial, the bounce time is 10ms. We can use the impulse response of a LPF to 'ignore' the first 10 or more milliseconds of the button press. In other worse, t1 should be at least 10ms.

So how do we choose the values of C and R in order to obtain a t1 of 10ms? There is a decent amount of math and deeper understanding of circuits required that's beyond the scope of this tutorial. So instead, we'll use a cool online tool that allows us to enter different values for R and C, and shows us the impulse response and frequency response of that LPF: http://sim.okawa-denshi.jp/en/CRtool.php

By inputting different value of R and C, we can see how the cutoff frequency changes, but more importantly, how the rise time changes. So play around until we obtain a value of t that's around 10ms. The values I chose are R = 10 kOhm, and C = 4.7 uF, which yield a t of about 10.82ms.

Perfect! we now have a Low pass filter that will allow us to 'ignore' the bounce time of the button, and give the output a clean, stable signal!


Method 2: Schmitt Trigger

The Schmitt trigger is another circuit we can use to create a clean, noise-free output from a noisy input. Since the circuit of a Schmitt trigger is much more complex than that of a LPF, I'll let you read more about it yourself: https://howtomechatronics.com/how-it-works/electrical-engineering/schmitt-trigger/

What we do need to understand is that a Schmitt trigger can create the following effect:

Image result for schmitt trigger for debounce

which serves the exact purpose we want of mitigating the unwanted noise from the imperfect metal contact in the button press.


For this tutorial, we will implement button debouncing using both methods, first a LPF, then a Schmitt trigger (the part will be provided).

Now, our block diagram becomes:



Requirement 2: Use our micro-controller (STM32F072CBT6)

If you've never played around with an Arduino or something similar before, you may not be familiar with what a micro-controller is. Please take the time to read about what a micro controller is and come back to the tutorial. 

I'm now going to explain how to incorporate our micro controller into this board, and use it to turn on the LEDs when the buttons are pressed.

In the car, various boards are placed in different parts of the car to serve different purposes. For example, the Pedal Board reads in analog signals from the accelerator and brake pedals. These raw analog values are translated to a percentage between 0 - 100% by calibrating the pedal board. These values are then sent to other boards in the car, where they are eventually used to control how much torque our motors should be outputting. Before this happens though, we need to make sure that the car is safe to drive. This includes checking things like is the driver pressing the brake pedal, or is the vehicle plugged into an EV charging station? All of this logic is handled on the microcontrollers in their respective boards. To simplify each board, we designed a Controller Board that consists of: The microcontroller, regulator, and CAN transceiver. 

Here's an overly simplified explanations of how we use micro controllers: In the car, many PCBs placed in various places in the vehicle, need to communicate with one another. In order for this communication to occur, we need to use micro controllers on these boards. Now, instead of having to add the same micro controller to every board (can be very tedious during board development), we created a 'Controller Board'. This is a generic board that includes our micro controller (and does a couple other things) that we attach on all of the boards that require an MCU (micro controller unit). What this means is that we can make many of the same 'controller board', and attach them to different 'Carrier boards' in order to add an MCU to that carrier board. 

We call it a carrier board because it carries our controller board. An example looks like:

The highlighted greed board is the 'Controller board' and the blue board is the 'Carrier board' (it's our Center Console board). It literally sits on top of our board, and makes electrical connections to the controller board (we'll see more of how this works when we begin the PCB layout).

So, we want to use this MCU in order to take in the button signals as inputs, and have the LEDs as outputs. Then we add some code onto the MCU like if(b1 == 1) then led1 = 1; basically we read the signal that the button gives, and if we sense that it went high, then we give power to the LED which will turn it on. For this tutorial, we simply need to create the electrical connections for this to work - we won't worry about code. So, your task is to learn more about our MCU by reading the datasheet and choosing appropriate GPIOs (General Purpose Input/Outputs) to route the buttons and LEDs to.

(If you're having trouble understanding the datasheet, and knowing which pins to choose, please ask one of our core members, and they'll help you out!)

Great! So now we can fill our block diagram even more:


Awesome! We're almost done. The only thing remaining is that we need to limit the current that goes through the LEDs. Have you ever directly connected an LED to a battery? If you haven't, the LED will likely burn out! This is because there is a large amount of current going through the LED. Since LEDs are rated for a maximum current, we need to limit the current and voltage going through the LED. A simple google search of "How to pick a resistor for an LED" can tell you exactly how to pick the value of the resistor required in series before the LED. All you need is some information from the LED datasheet. In particular, pay attention to the forward current and forward voltage of the LED.

In our case, according to the datasheet, the forward voltage is between 2 V to 2.4 V, and the forward current is rated at 20 mA. 

For the forward current, the rated current is up to 100 mA, but the LED was tested at 20 mA. For LEDs, the forward current is proportional to the brightness of the LED. Since we only need the LEDs to be an indicator, anywhere from 5 - 20 mA should be ok. For now, we'll assume a current of 10 mA and we can adjust our resistor based on the LEDs brightness once the board is brought up. 


Finally, our block diagram looks like:


Now that we understand the board requirements, and we have a block diagram for our circuit, we can begin the PCB layout process using Altium Designer.


PCB Layout - Altium Designer

Overhead:

So, in order to bring our circuit design to life, we first need to realize it using a piece of software called Altium Designer. If you don't know what Altium is, take a minute to read about what it is, and download it here (Note: Do not download the free trial, we have a midnight sun account you can use to download. Ask one fo our leads for the credentials).

Unfortunately, Altium is only available for Windows, so if you use Mac, consider using a Virtual Machine, or Dual booting using Bootcamp.

Now that we have Altium downloaded, we're ready to clone the Midnight Sun Hardware Git repository in order to have access to all our existing projects, as well as begin new ones for your tutorial. Luckily, our confluence has a great document on how to do exactly that, which can be found here (Tip: if you're on windows, I recommend downloading Git Bash since native terminal doesn't have git on Windows).

Great! After reading and following the document mentioned, you should now have all our projects downloaded locally, and you should also know how to create a new branch for a new project (if you don't know how Git works, take some time to learn about how it works). Since we're starting a new project, go ahead and create a new branch called 'hw_tutorial_[your_name]'. This will be the branch where you will do your development for this tutorial. 

Creating the Project:

Now we're ready to start a new Altium project, and begin our schematic layout. However, since setting up a brand new project can require a lot of overhead work that is repetitive, we've gone ahead and created a template for any new 'Carrier Board' that we need to make. And if you remember from earlier, this tutorial requires you to make a carrier board, since our controller board will be attached to it.

To begin, make a new folder inside the '../hardware' directory called 'MSXII_HW_Tutorial_[your_name]',


then go into 'MSXII_Templates\MSXII_CarrierBoardTemplate' folder and copy all files from that folder into the folder you just created. This essentially creates a Carrier Board project for you, instead of having to go through a bunch of settings and parameters. Now go ahead and open the Altium project file that you just copied into your new folder.

Creating the Schematic:

Welcome to Altium Designer! If there are no issues, you should see a project panel on the left hand side, go ahead and double click 'Controller_Board_Interface.SchDoc' 

This will open the schematic diagram of your PCB. The schematic diagram is essentially like a block diagram that contains 'schematic symbols' for all the parts that go onto the board; it also includes all connections that need to be made between parts (wire connections). 

What you see here is a schematic symbol (yellow rectangle) for the connector that your board requires in order to plug in the controller board. This is important, and we need it! If you notice, it has assigned pins. These pins correspond to the actual pin assignments of the MCU that we're using on our Controller board. Essentially, if you want to connect something on your board to the MCU, you connect it to its respective pin on the connector - It's an indirect connection, since the MCU isn't physically on our Carrier board. 

Note that the pins are named as follows: 

  • PXY: Port X Pin Y
  • ANz: Analog input Z
  • SPI/I2C/UART pins as labelled 
  • LED_COLOUR: Try and not use these if you can. These pins are connected to the debug LEDs on the controller board. 

The Mezzanine_Interface on the right of the connector isn't needed for now, so go ahead and drag over it to remove (del) it along with its connections.

Now you're ready to begin layout out the schematic for your board. One thing that's great about our work-flow is that we have a shared library that contains all the electrical parts that we've ever used in our past projects! Everything from resistors and capacitors, to buttons and switches, to LEDs and Integrated Circuits (chips or ICs). Part of this tutorial will teach you how to add a new part to our library, but for now, I'll show you how to use it to add parts to your schematic!

In order to place a new part in your schematic, go ahead and press 'Place → Part' or simply press 'pp' on your keyboard. The following panel will appear:

make sure the drop-down menu has "Schematic Diagrams.SchLib" selected. This is because we're in the schematic layout (each part has a schematic symbol, for the schematic, and a physical footprint that's used for the PCB layout). This list will have all our parts (I recommend you sort the list by Designator ID). Let's start with our buttons, go ahead and find the following part(s): "SW SPST-NO 0.1A 32V D6 ...". You'll see that there's a few of them. They're just different colours. Pick the one you want, and drag the symbol onto your schematic sheet. This will place it on your schematic:

And that's how you place a part! Super easy! Now go ahead and choose a different colour button for your second one, and place it on. (It's important that your schematic is aesthetically clear. So place things nicely, and feel free to move things around). Now to make connections, you can select 'Place → Wire" or ctrl+w, then press to begin laying a wire. Altium will show you if a new connection is being made by showing a thin large red 'X' over your cursor when you hover over a possible connection. Go ahead and place wires before and after the buttons:


Connections:

As we just did, connections in Altium can be done using a physical wire connection between the two components we wish to connect. However, this is not the only way! A lot of times, for aesthetic reasons or otherwise, we cannot make a physical connection between the two components. In this case, we can use 'NetLabels'. A NetLabel allows us to make connections without using a physical wire. In fact, you've already seen NetLabels! On the connector, you see red text that describes the pin - that's a NetLabel! Not only that, but power/ground indicators (+12V, 3V3, GND) are also all NetLabels.

For instance, we know we want to connect the left side of the button to power (3V3), we also want to connect the right side of the button to an input on the MCU connector (Ignore filtering for now). We can do the following:

To place a NetLabel go to 'Place → NetLabel' or 'pn' on your keyboard. The NetLabel must be properly connected to a pin or an existing wire to properly function. All wires or pins that you want to connect using a NetLabel MUST have the same NetLabel on all of them.

Note: In Altium, any connection falls under a 'Net'. If multiple things are connected to the same connection (i.e. Ground or PA10), then they belong to the same Net.

Now in the photo above, as far as Altium is concerned, the buttons are both connected to power, 3V3 (In parallel), and to PA10 and PA09 respectively. Even if there's no physical wire connection, the connection is there and Altium is happy.

But these aren't the right connections... We need filters between the buttons and MCU. We also need to decide which pins to connect the buttons to. I'll leave it up to you to go into the datasheet and decide which pins to use (Starting page 33. We're using the LQFP48 package). 

At this point you should have enough information to complete our block diagram, except for one thing: the Schmitt Trigger. We have 1-channel Schmitt Triggers in our library, but I wanna take this time to introduce you to another very important step in our development: Adding parts to our library. So, let's find and add a 2-Channel Schmitt Trigger to our library, so we can use it for our buttons.

Since finding a part can be intimidating on Digikey, we'll go ahead and find the part for you, but be sure to ask one of our leads about how we choose parts because it's very important!

Finding a Component on Digikey

We mostly source our components from Digikey and Mouser. In this example, you will be looking for a 2-Channel Inverter with a schmitt trigger input. This will be powered by the 3.3V supply, so we should make sure that it can operate at 3.3V. For most components, we try and use Automotive Qualified (AEC-Q) components whenever possible. These components are stress tested by the manufacturer to meet automotive reliability requirements. This is however, optional so use your best judgement as to if we should use a AEC-Q component or not. 

  1. Search Schmitt trigger on Digikey. Since we want a logic gate/inverter, choose the first one: Logic - Gates and Inverters

  2. Some basic filters that you can apply every time for pretty much any components:
  • Stock Status: In Stock
  • For most IC/Resistor/Capacitor/Inductor/Diodes/Transistors: Packaging: Cut-Tape
  • Part Status: Active



3. Now we can add filters for our specific component, namely:

  • Series: Any that says Automotive in it
  • Number of Circuits: 2
  • Logic type: Inverter

4. After applying the filters, we have 8 options remaining. We can now either filter by Voltage - Supply to make sure they work with 3.3 V inputs, or we can just sort by price and look at the cheapest ones available to see if they work for our purpose.

The first component when I sorted by price was the NXP 74LVC2G14GW-Q100H. Looking at the datasheet, we should make sure that the part will work for our purposes:

Can it be powered by 3.3V and interface with 3.3V logic? 

Yes, 3.3 V is within the recommended supply voltage range. So this should work. 


We'll go ahead and use this part: https://www.digikey.ca/product-detail/en/nexperia-usa-inc/74LVC2G14GW-Q100H/1727-2072-1-ND/5221591 with the following datasheet. Now, to add this part to our library, have to do a few things:

  1. Let's start with adding the schematic symbol. Navigate to our Schematic Library from the project finder 'Libraries → Schematic Library Documents → Schematic Documents.SchLib' and double click to open. Choose 'SCH Library' from the bottom panel, and you should see a list of all the schematic symbols for all our parts in our library.

    To add a new schematic symbol, press 'Add' and put the name thats under the Description of the part on Digikey - in our case it's 'IC INVERTER SCHMITT 2CH 6TSSOP'. Then navigate to your new part and click one part, and click 'Edit'. 

    For the designator, input 'U?' (U is for all ICs, and the '?' tells Altium that it can be annotated with a number later in the schematic). A full list of the reference designators are available For the description, input the 'Detailed Description' of the part as found on Digikey: "Inverter IC 2 Channel Schmitt Trigger 6-TSSOP" in our case.

    Now it's time to actually draw the schematic symbol that we'd see in our schematic diagrams. We can use a simple rectangle with 'pins' to denote the different pins on our IC.
    To place a rectangle shape, go to 'Place → Rectangle' and click to set the start and finish of the shape. Then to place pins, go to 'Place → Pin' and place it to look like the following (you'll have to play around with orientation and such)
     (we like to keep Vcc at the top, and GND at the bottom; inputs on the left and outputs on the right)

    So now this is what it'll look like on our schematic sheet when we use it. Another important step is adding the manufacturer details and supplier information to the library. Here's how we do that:
    Click on 'Panels' on the bottom right of your screen and select 'Manufacturer Part Search'. This will bring up a panel on the left that you can use to link the part we found on Digikey, to the part in the Library (This is very important when we're creating our BOM when we buy the parts for the board). Copy and paste the digikey part number and paste it in the 'search' bar. 

    Click on the little arrow to expand the parts, then right click the part number and choose 'Add Supplier Link and Parameters to ... ". You should now see the supplier link on the bottom left panel of your SCH Library panel. Be sure to save the Schematic Diagrams.SchLib file as you make changes.

  2. Let's now go and add a footprint for this part so we can link it to our schematic. To add a footprint, open the 'Libraries → PCB Library Documents → Footprints.PcbLib'. Open the PCB Library panel on the bottom left, and you'll see a familiar panel. We're going to use a tool to help us create the footprint easily just by inputting parameters. Go to 'Tools → IPC Compliant Footprint Wizard'. 
    This is a Wizard tool that we generally use for more complicated ICs and such. It's pretty easy to follow: the only thing you need is the part datasheet. Choose the SOP/TSOP option, and hit next

    You'll now notice that it's asking you about measurements for the part. To find these exact values, go to page 12 (the package we chose), and fill the parameters accordingly. Be very careful and precise!
    For this part, it's ok to use calculated values for most of the parameters following the initial form. However, select 'Rectangle' when presented with the pad layout (instead of Rounded). Also be sure to select 'Generate STEP Model Preview' on the bottom left corner of the wizard.
    Input the same name and description as for the schematic, and click 'Finish'. The footprint is now complete, we now need to go back to our schematic, and 'Add Footprint' and choose our newly created footprint.

    Our part has now been successfully added, and we can now import our library changes by going back to our schematic document, select 'Tools → Update from Libraries'. Now when we place a new part, it will show up.

Now that we've added the new Schmitt Trigger, we can finish our schematic. Do so on your own, and show one of our leads once you're finished, or ask them for help if you get stuck at any point in the process - I know that was a lot!!