Overview

In this tutorial, we’ll build a simple blinking LED circuit using a 555 timer. We’ll go step by step through each stage of building the circuit, then finish by exporting for manufacturing and publishing our circuit for others to inspect on the tscircuit registry.

Want to skip to the source code? Check out the github repository

Build a Blinking LED Circuit with React!

Initializing your Project

Create a new directory called blinking-led-circuit and run tsci init, this will bootstrap the project structure.

Now run tsci dev to get a preview window.

Rename lib/MyCircuit.tsx to lib/BlinkingLedCircuit.tsx.

Make sure the example file correctly imports your circuit:

examples/MyCircuit.tsx
import { BlinkingLedCircuit } from "lib/BlinkingLedCircuit"

export const MyExample = () => <BlinkingLedCircuit />

Add Battery and 555Timer from Registry

Run tsci add @tscircuit/battery @tscircuit/a555timer to add the battery and 555 timer to your project.

Let’s modify our circuit to…

lib/BlinkingLedCircuit.tsx
import { Battery } from "@tsci/tscircuit.battery"
import { A555Timer } from "@tsci/tscircuit.a555timer"

export const BlinkingLedCircuit = () => (
  <group>
    <Battery center={[-5, 0]} name="BAT" voltage="9V" />
    <A555Timer name="U1" />
  </group>
)

You should now see see our imported components appear in the schematic view!

Our circuit now has a battery and a 555 timer!

Add Passive Components

lib/BlinkingLedCircuit.tsx
import { Battery } from "@tsci/tscircuit.battery"
import { A555Timer } from "@tsci/tscircuit.a555timer"

export const BlinkingLedCircuit = () => (
  <group>
    <Battery center={[-5, 0]} name="BAT" voltage="9V" />
    <A555Timer name="U1" />
    <resistor name="R1" resistance="1K" x={-2.5} y={-1} rotation="90deg" />
    <resistor name="R2" resistance="470K" x={-2.5} y={1} rotation="90deg" />
    <resistor name="R3" resistance="1K" x={2} y={1} rotation="90deg" />
    <diode name="D1" x={2} y={3} rotation="90deg" />
    <capacitor name="C1" capacitance="1uF" x={-2.5} y={3} rotation="90deg" />
  </group>
)

Passives added!

Add Traces

lib/BlinkingLedCircuit.tsx
import { Battery } from "@tsci/tscircuit.battery"
import { A555Timer } from "@tsci/tscircuit.a555timer"

export const BlinkingLedCircuit = () => (
  <group>
    <Battery center={[-5, 0]} name="BAT" voltage="9V" />
    <A555Timer name="U1" />
    <resistor name="R1" resistance="1K" x={-2.5} y={-1} rotation="90deg" />
    <resistor name="R2" resistance="470K" x={-2.5} y={1} rotation="90deg" />
    <resistor name="R3" resistance="1K" x={2} y={1} rotation="90deg" />
    <diode name="D1" x={2} y={3} rotation="90deg" />
    <capacitor name="C1" capacitance="1uF" x={-2.5} y={3} rotation="90deg" />
    <trace from=".BAT > .plus" to=".R1 > .left" />
    <trace from=".R1 > .right" to=".R2 > .left" />
    <trace from=".R2 > .right" to=".C1 > .left" />
    <trace from=".C1 > .right" to=".BAT > .minus" />
    <trace from=".C1 > .right" to=".D1 > .right" />
    <trace from=".U1 > .DISCH" to=".R1 > .right" />
    <trace from=".U1 > .THRES" to=".R2 > .right" />
    <trace from=".U1 > .TRIG" to=".R2 > .right" />
    <trace from=".U1 > .OUT" to=".R3 > .left" />
    <trace from=".D1 > .left" to=".R3 > .right" />
  </group>
)

Our circuit now has traces!

Set the passive footprints

The footprint or “landing pattern” is the physical copper pad that a component is soldered to on a PCB. We need to set the footprints for our passive components. For this circuit, we’ll use the 0805 package for all of our passive components and the LED.

lib/BlinkingLedCircuit.tsx
// ...
  <resistor
    name="R1"
    resistance="1K"
    x={-2.5}
    y={-1}
    rotation="90deg"
    footprint="0805"
  />
  <resistor
    name="R2"
    resistance="470K"
    x={-2.5}
    y={1}
    rotation="90deg"
    footprint="0805"
  />
  <resistor
    name="R3"
    resistance="1K"
    x={2}
    y={1}
    rotation="90deg"
    footprint="0805"
  />
  <diode name="D1" x={2} y={3} rotation="90deg" footprint="0805" />
  <capacitor
    name="C1"
    capacitance="1uF"
    x={-2.5}
    y={3}
    rotation="90deg"
    footprint="0805"
  />
// ...

When you hover over the 0805 footprint, you can see they're all on top of each other!

Layout the PCB

We can now lay out the pcb by setting the position of each component. In the future, it’ll be possible to do this with auto-layout similar to web’s flexbox or grid, but for now we’ll set the X and Y manually with pcb_x and pcb_y.

lib/BlinkingLedCircuit.tsx
// ...
    <Battery
      center={[-5, 0]}
      pcb_x={20}
      pcb_y={-10}
      pcb_rotation="90deg"
      name="BAT"
      voltage="9V"
    />
    <A555Timer pcb_x={20} pcb_y={0} name="U1" />
    <resistor
      name="R1"
      resistance="1K"
      x={-2.5}
      y={-1}
      pcb_x={10}
      pcb_y={5}
      rotation="90deg"
      footprint="0805"
    />
    <resistor
      name="R2"
      resistance="470K"
      x={-2.5}
      y={1}
      pcb_x={10}
      pcb_y={-5}
      rotation="90deg"
      footprint="0805"
    />
// ...

Our footprints are now on the board, but some traces are overlapping!

Fixing Overlapping Traces

tscircuit currently only auto-routes for single layers and ignores other traces, this prevents complex and sometimes “characteristic” traces from being routed. We can manually route the traces using pcb_route_hints to specify vias or more complex routes.

It’s okay to have overlapping traces if they’re within the same net, future versions of tscircuit will show an error and refuse to route overlapping traces!

You can double click inside the PCB Viewer to see the coordinate of your cursor!

lib/BlinkingLedCircuit.tsx
// ...
    <trace
      from=".R2 > .right"
      to=".C1 > .left"
      pcb_route_hints={[
        {
          x: 12,
          y: -4,
          via: true,
        },
        {
          x: 8,
          y: 8,
          via: true,
        },
      ]}
    />
// ...

Before adding pcb_route_hints

After adding pcb_route_hints, the trace now goes to the bottom layer!

Generate Gerber Files

Gerbers are the de-facto format for getting a PCB printed. You can go to File > Export > Gerbers to get a zip file suitable for upload to jlcpcb, pcbway, MacroFab, or any other PCB manufacturer.

Export Gerbers from File > Export > Gerbers

Add Supplier Part Numbers for Easy Ordering & Assembly

A supplier can often take a Bill of Materials (BOM) and Pick’n’Place file (pnp.csv) and completely assemble your circuit. You can export the BOM and PnP files from File > Export, but before you export you’ll need to indicate the part numbers that should be used from each supplier. You can do that with the supplier_part_numbers prop like so:

lib/BlinkingLedCircuit.tsx
// ...
<resistor
  resistance="220"
  name="R3"
  pcb_x={30}
  pcb_y={5}
  supplier_part_numbers={{
    jlcpcb: ["C3000591"],
  }}
  footprint="1210"
  rotation="90deg"
  center={[3, 2]}
/>
// ...

Publish to Registry

When you’re ready to share your circuit with the world, or use your circuit as a sub-circuit of a larger project, you can publish your circuit with tsci publish

Bonus: Ordering the PCB

Coming soon!