initial commit

This commit is contained in:
s3lph 2024-09-11 01:41:41 +02:00
commit 74b9c0c995
Signed by: s3lph
GPG key ID: 0AA29A52FB33CFB5
19 changed files with 22272 additions and 0 deletions

64
README.md Normal file
View file

@ -0,0 +1,64 @@
# SpaceAPI LED Map
A map of hackerspaces lasercut from plywood, with their [SpaceAPI][spaceapi] opening states shown in red and green LEDs.
The LEDs are WS2812-compatible bulb-shaped LEDs, and they are controlled by an ESP32-C3 board.
This is a work in progress (2nd half 2024) project; documentation will be updated as the project progresses.
## Contents of This Repository
### erfamap-output/
The data for lasercutting the map was generated using a modified
version of my [Erfamap][erfamap] project, which uses the
[api.spaceapi.io][api.spaceapi.io] SpaceAPI aggregator instead of the
CCC internal Wiki to determine which dots to place where. A lot of
this data was edited by hand in order to improve it for laser cutting.
- `spaceapi-info.json` is the cache file used by the modified script.
It has been edited manually to remove some entries which had broken
or unsuitable API endpoints.
- `map.svg` is the output file generated by the modified script.
- `map-prepared.svg` is the file that has been prepared for laser cutting and engraving:
- Labels have been move manually so that they are easier to assign to the correct LED, and so they don't overlap with any of the country borders.
- Text has been converted to paths.
- All paths have been assigned to layers corresponding to how they should be processed.
The modified Erfamap script will be released at a later point after some further cleanup.
### pcb/
The KiCad project for the PCBs that connect everything together.
Each PCB connects to 10 LEDs, and the PCB can be chained together to
form a single WS2812 chain. There are 83 LEDs in the current version, so a total of 9 of these PCBs is required.
The ESP32-C3 needs to be soldered to the first PCB.
### esp32/
The PlatformIO Arduino project for the ESP32. It perfoms the following tasks:
- Connect to the WiFi network defined at compile time
- Obtain the current time through NTP
- Fetch the aggregated SpaceAPI responses from api.spaceapi.io and parse the JSON response
- Update the WS2812 LEDs
Compile and upload to the ESP32 using PlatformIO:
```bash
export ESP32_WPA2_SSID=the-wifi-ssid
export ESP32_WPA2_PSK=the-wifi-psk
pio run -t upload
```
## Components
- WS2812-compatible 5mm bulb LEDs: https://de.aliexpress.com/item/1005005003701575.html
- Black 5mm LED sockets: https://de.aliexpress.com/item/1005005062684329.html
- ESP32-C3 Super Mini: https://de.aliexpress.com/item/1005006252882434.html
- JST-ZH cables: https://de.aliexpress.com/item/1005007298855435.html
[spaceapi]: https://spaceapi.io
[erfamap]: https://git.kabelsalat.ch/s3lph/erfamap
[api.spaceapi.io]: https://api.spaceapi.io/

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 468 KiB

2459
erfamap-output/map.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 480 KiB

File diff suppressed because one or more lines are too long

1
esp32/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.pio

39
esp32/include/README Normal file
View file

@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

46
esp32/lib/README Normal file
View file

@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

23
esp32/platformio.ini Normal file
View file

@ -0,0 +1,23 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32-c3-devkitm-1]
platform = espressif32
board = esp32-c3-devkitm-1
framework = arduino
lib_deps =
adafruit/Adafruit NeoPixel@^1.12.3
bblanchon/ArduinoJson@^7.1.0
sstaub/NTP@^1.6
build_flags =
-D ARDUINO_USB_MODE=1
-D ARDUINO_USB_CDC_ON_BOOT=1
-D WPA2_SSID=${sysenv.ESP32_WPA2_SSID}
-D WPA2_PSK=${sysenv.ESP32_WPA2_PSK}

149
esp32/src/main.cpp Normal file
View file

@ -0,0 +1,149 @@
#include <Arduino.h>
#include <WiFiClientSecure.h>
#include <WiFiUdp.h>
#include <NTP.h>
#include <Adafruit_NeoPixel.h>
#include <ArduinoJson.h>
#include "spacemap.h"
#ifndef WPA2_SSID
#define WPA2_SSID "my-wifi-ssid"
#endif
#ifndef WPA2_PSK
#define WPA2_PSK "change-me"
#endif
#define WIFI_RETRY 120
#define WS2812_PIN 0
#define WS2812_LEN (sizeof(spaces)/sizeof(char*))
#define WS2812_BS 5
#define SPACEAPI_HOST "api.spaceapi.io"
#define SPACEAPI_PORT 443
#define SPACEAPI_PATH "/"
WiFiClientSecure client;
WiFiUDP wifiUdp;
NTP ntp(wifiUdp);
Adafruit_NeoPixel pixels(WS2812_LEN, WS2812_PIN, NEO_RGB | NEO_KHZ800);
JsonDocument json, filter;
void connectAndWait() {
if (!WiFi.status() != WL_CONNECTED) {
pixels.clear();
pixels.setPixelColor(0, pixels.Color(WS2812_BS*2, 0 , 0));
pixels.show();
Serial.println("\nConnecting to WiFi Network ..");
WiFi.mode(WIFI_STA);
WiFi.setTxPower(WIFI_POWER_15dBm);
WiFi.disconnect();
WiFi.begin(WPA2_SSID, WPA2_PSK);
}
uint16_t i = 0;
for (uint16_t i = 0; WiFi.status() != WL_CONNECTED && i < WIFI_RETRY; ++i) {
Serial.println(WiFi.status());
delay(250);
if (WiFi.status() == WL_DISCONNECTED) {
pixels.setPixelColor(0, pixels.Color(WS2812_BS*2*(i%2), 0, 0));
} else {
pixels.setPixelColor(0, pixels.Color(WS2812_BS*2*(i%2), WS2812_BS*(i%2), 0));
}
pixels.show();
}
if (i >= WIFI_RETRY) {
pixels.setPixelColor(0, pixels.Color(WS2812_BS, 0 , WS2812_BS));
pixels.show();
ESP.restart();
while (true) { Serial.print(""); };
}
Serial.println("\nConnected to the WiFi network");
Serial.print("Local ESP32 IP: ");
Serial.println(WiFi.localIP());
pixels.setPixelColor(0, pixels.Color(0, WS2812_BS*2, 0));
pixels.show();
}
void setup() {
Serial.begin(115200);
pixels.begin();
connectAndWait();
ntp.begin();
// setup json filter
filter[0]["url"] = true;
filter[0]["lastSeen"] = true;
filter[0]["data"]["state"]["open"] = true;
filter[0]["data"]["state"]["lastchange"] = true;
}
void loop() {
connectAndWait();
ntp.update();
Serial.println(ntp.formattedTime("\nIt is %d.%m.%Y %H:%M UTC"));
time_t now = ntp.epoch();
Serial.println("Starting connection to server...");
client.setInsecure();
if (!client.connect(SPACEAPI_HOST, SPACEAPI_PORT)) {
Serial.println("Connection failed!");
} else {
Serial.println("Connected to server!");
client.print("GET ");
client.print(SPACEAPI_PATH);
client.println(" HTTP/1.0");
client.print("Host: ");
client.println(SPACEAPI_HOST);
client.println("Connection: close");
client.println();
while (client.readStringUntil('\n') != "\r");
}
DeserializationError error = deserializeJson(json, client, DeserializationOption::Filter(filter));
if (error) {
Serial.print("deserializeJson() failed: ");
Serial.println(error.f_str());
} else {
pixels.clear();
for (uint16_t i = 0; i < json.size(); ++i) {
int16_t pi = -1;
for (uint16_t j = 0; j < WS2812_LEN; ++j) {
if (spaces[j] == json[i]["url"]) {
pi = j;
break;
}
}
if (pi < 0) {
continue;
}
if (json[i]["data"] == nullptr || json[i]["data"]["state"] == nullptr || json[i]["data"]["state"]["open"] == nullptr || !json[i]["data"]["state"]["open"].is<bool>()) {
pixels.setPixelColor(pi, pixels.Color(WS2812_BS*2, WS2812_BS, 0));
Serial.println(": invalid!");
} else {
Serial.print(spaces[pi]);
time_t last = json[i]["lastSeen"].as<time_t>();
time_t last2 = last;
if (json[i]["data"]["state"]["lastchange"] != nullptr) {
last2 = json[i]["data"]["state"]["lastchange"].as<time_t>();
}
if (now - last > 24*3600) {
pixels.setPixelColor(pi, pixels.Color(0, 0, WS2812_BS*2));
Serial.println(": outdated!");
} else {
if (json[i]["data"]["state"]["open"].as<bool>()) {
pixels.setPixelColor(pi, pixels.Color(0, WS2812_BS*2, 0));
Serial.println(": open");
} else {
pixels.setPixelColor(pi, pixels.Color(WS2812_BS*2, 0, 0));
Serial.println(": closed");
}
}
}
}
pixels.show();
}
client.stop();
delay(300 * 1000);
}

95
esp32/src/spacemap.h Normal file
View file

@ -0,0 +1,95 @@
const char* spaces[] = {
// 0
"https://www.posttenebraslab.ch/status/status.json",
"https://fixme.ch/cgi-bin/spaceapi.py",
"https://status.crdmp.ch/",
"https://spaceapi.kabelsalat.ch/",
"https://spaceapi.odenwilusenz.ch/api.json",
"https://toolbox-bodensee.de/toolboxbodensee.json",
"https://vspace.one/spaceapi.json",
"http://cccfr.de/status/spaceapi.py",
"https://api.section77.de/",
"http://club.entropia.de/spaceapi",
// 1
"https://api.nerd2nerd.org/status.json",
"https://status.schaffenburg.org/spaceapi.php",
"https://www.ccc-mannheim.de/spaceapi/spaceapi.json",
"https://api.chaos-darmstadt.de/",
"https://status.ccc-ffm.de/spaceapi.json",
"https://api.westwoodlabs.de/spaceapi",
"https://api.haxko.space/",
"http://spaceapi.hacksaar.de/status.json",
"https://spaceapi.c3l.lu/status.json",
"https://maschinenstate.42dots.de/",
// 2
"https://www.devtal.de/api/",
"https://chaosdorf.de/space_api.json",
"https://api.koeln.ccc.de/",
"https://status.aachen.ccc.de/spaceapi",
"https://spaceapi.tdvenlo.nl/spaceapi.json",
"https://hackalot.nl/statejson",
"https://status.brixel.space/api/status",
"https://api.hsbxl.be/index.php/0.1/spaceapi/",
"https://spaceapi.voidwarranties.be/",
"https://spaceapi.pixelbar.nl/",
// 3
"http://techinc.nl/space/spacestate.json",
"https://state.awesomespace.nl/",
"https://bitlair.nl/statejson.php",
"https://space.nurdspace.nl/spaceapi/status.json",
"https://state.hackerspacenijmegen.nl/state.json",
"https://hack42.nl/spacestate/json.php",
"https://spaceapi.tkkrlab.nl/",
"https://mqtt.hackerspace-drenthe.nl/spaceapi",
"https://maakplek.nl/api/",
"http://frack.nl/spacestate/?api",
// 4
"http://status.mainframe.io/api/spaceInfo",
"https://status.space.bi/status.json",
"https://c3pb.de/uptime.json",
"https://api.warpzone.ms/spaceapi",
"https://spaceapi.c3re.de/",
"https://status.chaospott.de/status.json",
"http://status.ctdo.de/api/spaceapi/v13",
"https://keinanschluss.un-hack-bar.de/spaceapi.json",
"https://hsmr.cc/spaceapi.json",
"https://state.maglab.space/spaceapi.json",
// 5
"https://port39.de/spaceapi.json",
"https://hacklabor.de/api/space/v1/",
"https://status.metameute.de/status/spaceapi.json",
"https://spaceapi.hamburg.ccc.de/",
"https://status.stratum0.org/status.json",
"https://freieslabor.org/api/info",
"https://api.flipdot.org/",
"https://spaceapi.eigenbaukombinat.de/status_ebk.json",
"https://spaceapi.ccc-p.org/",
"https://spaceapi.afra-berlin.de/v1/status.json",
// 6
"https://status.makerspace-erfurt.de/status.json",
"https://status.kraut.space/api",
"http://api.service.z-labor.space/spaceapi.json",
"https://chaoschemnitz.de/chch.json",
"https://www.c3d2.de/spaceapi.json",
"https://www.werkraum.space/spaceapi/current/",
"https://brmlab.cz/spaceapi/brmstatus.json",
"https://spaceapi.hackzogtum-coburg.de/",
"https://status.bckspc.de/spacestatus.php",
"https://status.nerdberg.de/api/space",
// 7
"https://complb.de/spaceapi.json",
"https://api.shackspace.de/v1/spaceapi",
"https://spaceapi.ctbk.de/",
"https://spaceapi.sfz-aalen.space/api/spaceapi.json",
"https://spaceapi.temporaerhaus.de/spaceapi.json",
"http://api.openlab-augsburg.de/data.json",
"http://stats.bytewerk.org/status.json",
"https://www.binary-kitchen.de/spaceapi.php",
"https://api.muc.ccc.de/spaceapi.json",
"https://spaceapi.it-syndikat.org/api/status.php",
// 8
"https://devlol.org/status/hackerspaceapi/",
"https://segvault.space/internal/spacecore/opendata/spaceapi",
"http://realraum.at/status.json"
};

11
esp32/test/README Normal file
View file

@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html

33
pcb/.gitignore vendored Normal file
View file

@ -0,0 +1,33 @@
# For PCBs designed using KiCad: https://www.kicad.org/
# Format documentation: https://kicad.org/help/file-formats/
# Temporary files
*.000
*.bak
*.bck
*.kicad_pcb-bak
*.kicad_sch-bak
*-backups
*.kicad_prl
*.sch-bak
*~
_autosave-*
*.tmp
*-save.pro
*-save.kicad_pcb
fp-info-cache
# Netlist files (exported from Eeschema)
*.net
# Autorouter files (exported from Pcbnew)
*.dsn
*.ses
# Exported BOM files
*.xml
*.csv
# Exported production data by the Fabrication Toolkit extension
production
fabrication-toolkit-options.json

4
pcb/fp-lib-table Normal file
View file

@ -0,0 +1,4 @@
(fp_lib_table
(version 7)
(lib (name "ledbcp")(type "KiCad")(uri "${KIPRJMOD}/ledbcp.pretty")(options "")(descr ""))
)

View file

@ -0,0 +1,422 @@
(footprint "ESP32C3"
(version 20240108)
(generator "pcbnew")
(generator_version "8.0")
(layer "F.Cu")
(property "Reference" "REF**"
(at 8.89 3.81 0)
(unlocked yes)
(layer "F.SilkS")
(uuid "f96a2232-2e2c-4d11-8afc-fdb6721207bd")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(property "Value" "ESP32C3"
(at 8.89 -21.59 0)
(unlocked yes)
(layer "F.Fab")
(uuid "9ae705d1-4181-4726-b6e8-c3a41c772a5f")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(property "Footprint" ""
(at 17.78 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "a51a0ed8-b521-4417-a261-117f3ba59359")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(property "Datasheet" ""
(at 17.78 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "628a328c-4b62-4945-9463-678a927d9dd6")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(property "Description" ""
(at 17.78 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "f8f62964-826a-4050-96e0-2796b19d2ed5")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(attr smd)
(fp_line
(start 0 1.27)
(end 0 2.54)
(stroke
(width 0.15)
(type default)
)
(layer "F.SilkS")
(uuid "7f4f9640-81c6-441d-8672-71c8cdbb306c")
)
(fp_line
(start 0 2.54)
(end 17.78 2.54)
(stroke
(width 0.15)
(type default)
)
(layer "F.SilkS")
(uuid "24c3d947-58eb-41ae-80cd-e5001aaa09c6")
)
(fp_line
(start 1.27 -19.05)
(end 17.78 -19.05)
(stroke
(width 0.15)
(type default)
)
(layer "F.SilkS")
(uuid "da65ddc0-426b-4071-8af7-53e0198f459c")
)
(fp_line
(start 5.08 -19.685)
(end 5.08 -13.97)
(stroke
(width 0.15)
(type default)
)
(layer "F.SilkS")
(uuid "6d18e32e-37c8-4116-aabd-b4a5beaef05b")
)
(fp_line
(start 5.08 -13.97)
(end 12.7 -13.97)
(stroke
(width 0.15)
(type default)
)
(layer "F.SilkS")
(uuid "efc70783-36bf-41e8-bea2-b0ea4fb876bf")
)
(fp_line
(start 12.7 -13.97)
(end 12.7 -19.685)
(stroke
(width 0.15)
(type default)
)
(layer "F.SilkS")
(uuid "8f661c99-a4f5-4181-af76-128a4d9d4da3")
)
(fp_line
(start 17.78 2.54)
(end 17.78 1.27)
(stroke
(width 0.15)
(type default)
)
(layer "F.SilkS")
(uuid "89da6282-7a30-4539-b495-289ffccb8ae9")
)
(fp_rect
(start 6.35 0.635)
(end 11.43 2.54)
(stroke
(width 0.15)
(type default)
)
(fill none)
(layer "F.SilkS")
(uuid "5d4bd31c-8411-4e3f-a21c-9a8f72622322")
)
(fp_line
(start 6.35 -6.35)
(end 10.16 -2.54)
(stroke
(width 0.12)
(type default)
)
(layer "Dwgs.User")
(uuid "d7f4032a-f9d7-43db-aea4-1ee606a72821")
)
(fp_line
(start 10.16 -10.16)
(end 6.35 -6.35)
(stroke
(width 0.12)
(type default)
)
(layer "Dwgs.User")
(uuid "93f7528d-191c-4d68-99ac-28c8fb2fb9ba")
)
(fp_line
(start 10.16 -2.54)
(end 13.97 -6.35)
(stroke
(width 0.12)
(type default)
)
(layer "Dwgs.User")
(uuid "ee2e3fde-2d42-40f7-a403-2ecd3db7eb89")
)
(fp_line
(start 13.97 -6.35)
(end 10.16 -10.16)
(stroke
(width 0.12)
(type default)
)
(layer "Dwgs.User")
(uuid "90598cdb-7ded-4536-bdc0-e978ac7c955b")
)
(fp_rect
(start 5.08 -20.32)
(end 12.7 -13.97)
(stroke
(width 0.12)
(type default)
)
(fill none)
(layer "Dwgs.User")
(uuid "1f8aa122-0235-4c6a-8cc8-67af021e15a5")
)
(fp_rect
(start 6.35 0.635)
(end 11.43 2.54)
(stroke
(width 0.12)
(type default)
)
(fill none)
(layer "Dwgs.User")
(uuid "dfdcbe3c-a8d1-4070-81b7-7c0ed1527988")
)
(fp_rect
(start 0 -19.05)
(end 17.78 2.54)
(stroke
(width 0.12)
(type default)
)
(fill none)
(layer "F.CrtYd")
(uuid "a9610289-965a-4db1-a751-c13c73d9aa4e")
)
(pad "1" smd rect
(at 0 -17.78)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(thermal_bridge_angle 45)
(uuid "ba0b81ff-dc27-4234-b0dc-25588d711e89")
)
(pad "2" smd roundrect
(at 0 -15.24)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "08e522ff-df37-49e1-923d-f02bd4239fda")
)
(pad "3" smd roundrect
(at 0 -12.7)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "38b6ada6-81e8-469f-91b1-ca780534db1b")
)
(pad "4" smd roundrect
(at 0 -10.16)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "64abb0eb-d3c4-42fb-87bc-8d75ca680afd")
)
(pad "5" smd roundrect
(at 0 -7.62)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "1092a262-76ec-4f9f-ac9f-5c234f77003c")
)
(pad "6" smd roundrect
(at 0 -5.08)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "1a238bd4-76a2-47d9-bcb0-82de17f75202")
)
(pad "7" smd roundrect
(at 0 -2.54)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "3cc046b7-7008-4303-b21c-190603d08932")
)
(pad "8" smd roundrect
(at 0 0)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "db93c649-4e4e-4441-a916-6e28da0b6133")
)
(pad "9" smd roundrect
(at 17.78 0)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "74fbbe11-a7de-42d6-b350-94e19c8607de")
)
(pad "10" smd roundrect
(at 17.78 -2.54)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "b60fcff5-a3d4-4cd2-9dee-d674157a3553")
)
(pad "11" smd roundrect
(at 17.78 -5.08)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "1ee20032-9c57-4319-8a38-408307711946")
)
(pad "12" smd roundrect
(at 17.78 -7.62)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "1678e28f-4946-4904-9858-b8aa7767cf42")
)
(pad "13" smd roundrect
(at 17.78 -10.16)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "390e95f7-ac12-4478-ae16-6ce0f6f4b5e3")
)
(pad "14" smd roundrect
(at 17.78 -12.7)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "e5793610-a49f-4ff5-bf78-aaac339c4e2a")
)
(pad "15" smd roundrect
(at 17.78 -15.24)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "1aa08acc-f98b-459c-bc47-38384ec2938a")
)
(pad "16" smd roundrect
(at 17.78 -17.78)
(size 3.81 1.524)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.25)
(thermal_bridge_angle 45)
(uuid "98235b17-c0c2-4955-be5e-a94eb5ef79ba")
)
(zone
(net 0)
(net_name "")
(layer "F.Cu")
(uuid "89629789-ba84-4526-9e57-951aace28e7b")
(name "WiFi Keepout Zone")
(hatch edge 0.5)
(connect_pads
(clearance 0)
)
(min_thickness 0.25)
(filled_areas_thickness no)
(keepout
(tracks not_allowed)
(vias not_allowed)
(pads not_allowed)
(copperpour not_allowed)
(footprints not_allowed)
)
(fill
(thermal_gap 0.5)
(thermal_bridge_width 0.5)
)
(polygon
(pts
(xy 15.875 -0.635) (xy 15.875 0.762) (xy 17.78 0.762) (xy 17.78 3.81) (xy 0 3.81) (xy 0 0.762) (xy 1.905 0.762)
(xy 1.905 -0.635)
)
)
)
(zone
(net 0)
(net_name "")
(layer "B.Cu")
(uuid "fd822c1b-4581-4324-8ec4-bbfff1aec972")
(name "WiFi Keepout Zone")
(hatch edge 0.5)
(connect_pads
(clearance 0)
)
(min_thickness 0.25)
(filled_areas_thickness no)
(keepout
(tracks not_allowed)
(vias not_allowed)
(pads not_allowed)
(copperpour not_allowed)
(footprints not_allowed)
)
(fill
(thermal_gap 0.5)
(thermal_bridge_width 0.5)
)
(polygon
(pts
(xy 17.78 -0.635) (xy 17.78 0.762) (xy 17.78 0.762) (xy 17.78 3.81) (xy 0 3.81) (xy 0 0.762) (xy 0 0.762)
(xy 0 -0.635)
)
)
)
(model "${KIPRJMOD}/ledbcp.pretty/ESP32C3-SuperMini.stp"
(offset
(xyz 8.89 8.255 0)
)
(scale
(xyz 1 1 1)
)
(rotate
(xyz 0 0 0)
)
)
)

10208
pcb/ledpcb.kicad_pcb Normal file

File diff suppressed because it is too large Load diff

619
pcb/ledpcb.kicad_pro Normal file
View file

@ -0,0 +1,619 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"apply_defaults_to_fp_fields": false,
"apply_defaults_to_fp_shapes": false,
"apply_defaults_to_fp_text": false,
"board_outline_line_width": 0.05,
"copper_line_width": 0.2,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.05,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.1,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.1,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.1,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.1,
"silk_text_upright": false,
"zones": {
"min_clearance": 0.5
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"connection_width": "warning",
"copper_edge_clearance": "error",
"copper_sliver": "warning",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_symbol_mismatch": "warning",
"footprint_type_mismatch": "ignore",
"hole_clearance": "error",
"hole_near_hole": "error",
"holes_co_located": "warning",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"lib_footprint_issues": "warning",
"lib_footprint_mismatch": "warning",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "warning",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_edge_clearance": "warning",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"solder_mask_bridge": "error",
"starved_thermal": "error",
"text_height": "warning",
"text_thickness": "warning",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zones_intersect": "error"
},
"rules": {
"max_error": 0.005,
"min_clearance": 0.0,
"min_connection": 0.0,
"min_copper_edge_clearance": 0.5,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.2,
"min_microvia_drill": 0.1,
"min_resolved_spokes": 2,
"min_silk_clearance": 0.0,
"min_text_height": 0.8,
"min_text_thickness": 0.08,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.0,
"min_via_annular_width": 0.1,
"min_via_diameter": 0.5,
"solder_mask_to_copper_clearance": 0.005,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_onpadsmd": true,
"td_onroundshapesonly": false,
"td_ontrackend": false,
"td_onviapad": true
}
],
"teardrop_parameters": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [
0.0,
0.1,
0.2,
0.3,
0.5
],
"tuning_pattern_settings": {
"diff_pair_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 1.0
},
"diff_pair_skew_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
},
"single_track_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
}
},
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
}
],
"zones_allow_external_fillets": false
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_presets": [],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"conflicting_netclasses": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"endpoint_off_grid": "warning",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"missing_bidi_pin": "warning",
"missing_input_pin": "warning",
"missing_power_pin": "error",
"missing_unit": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"simulation_model_issue": "ignore",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "ledpcb.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.2,
"via_diameter": 0.6,
"via_drill": 0.3,
"wire_width": 6
}
],
"meta": {
"version": 3
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"plot": "/tmp/foo/",
"pos_files": "",
"specctra_dsn": "",
"step": "",
"svg": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"bom_export_filename": "",
"bom_fmt_presets": [],
"bom_fmt_settings": {
"field_delimiter": ",",
"keep_line_breaks": false,
"keep_tabs": false,
"name": "CSV",
"ref_delimiter": ",",
"ref_range_delimiter": "",
"string_delimiter": "\""
},
"bom_presets": [],
"bom_settings": {
"exclude_dnp": false,
"fields_ordered": [
{
"group_by": false,
"label": "Reference",
"name": "Reference",
"show": true
},
{
"group_by": true,
"label": "Value",
"name": "Value",
"show": true
},
{
"group_by": false,
"label": "Datasheet",
"name": "Datasheet",
"show": true
},
{
"group_by": false,
"label": "Footprint",
"name": "Footprint",
"show": false
},
{
"group_by": false,
"label": "Qty",
"name": "${QUANTITY}",
"show": false
},
{
"group_by": true,
"label": "DNP",
"name": "${DNP}",
"show": true
},
{
"group_by": false,
"label": "#",
"name": "${ITEM_NUMBER}",
"show": true
},
{
"group_by": false,
"label": "LCSC",
"name": "LCSC",
"show": true
},
{
"group_by": false,
"label": "Description",
"name": "Description",
"show": false
}
],
"filter_string": "",
"group_symbols": true,
"name": "",
"sort_asc": true,
"sort_field": "Reference"
},
"connection_grid_size": 50.0,
"drawing": {
"dashed_lines_dash_length_ratio": 12.0,
"dashed_lines_gap_length_ratio": 3.0,
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"operating_point_overlay_i_precision": 3,
"operating_point_overlay_i_range": "~A",
"operating_point_overlay_v_precision": 3,
"operating_point_overlay_v_range": "~V",
"overbar_offset_ratio": 1.23,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"page_layout_descr_file": "",
"plot_directory": "",
"spice_current_sheet_as_root": false,
"spice_external_command": "spice \"%I\"",
"spice_model_current_sheet_as_root": true,
"spice_save_all_currents": false,
"spice_save_all_dissipations": false,
"spice_save_all_voltages": false,
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"2fa595f2-db69-4d05-b558-7bff3ae0df71",
"Root"
]
],
"text_variables": {}
}

5838
pcb/ledpcb.kicad_sch Normal file

File diff suppressed because it is too large Load diff

354
pcb/ledpcb.kicad_sym Normal file
View file

@ -0,0 +1,354 @@
(kicad_symbol_lib
(version 20231120)
(generator "kicad_symbol_editor")
(generator_version "8.0")
(symbol "ESP32C3"
(exclude_from_sim no)
(in_bom yes)
(on_board yes)
(property "Reference" "U"
(at -1.27 -1.27 0)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Value" ""
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Footprint" "ledbcp:ESP32C3"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Datasheet" ""
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Description" ""
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(symbol "ESP32C3_1_1"
(rectangle
(start 0 27.94)
(end 20.32 0)
(stroke
(width 0)
(type default)
)
(fill
(type background)
)
)
(pin bidirectional line
(at -5.08 7.62 0)
(length 5.08)
(name "D5"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "1"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at 25.4 20.32 180)
(length 5.08)
(name "D1"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "10"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at 25.4 17.78 180)
(length 5.08)
(name "D2"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "11"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at 25.4 15.24 180)
(length 5.08)
(name "D3"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "12"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at 25.4 12.7 180)
(length 5.08)
(name "D4"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "13"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at 5.08 33.02 270)
(length 5.08)
(name "3V3"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "14"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at 10.16 -5.08 90)
(length 5.08)
(name "GND"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "15"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at 15.24 33.02 270)
(length 5.08)
(name "5V"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "16"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at -5.08 10.16 0)
(length 5.08)
(name "D6"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "2"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at -5.08 12.7 0)
(length 5.08)
(name "D7"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "3"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at -5.08 15.24 0)
(length 5.08)
(name "D8"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "4"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at -5.08 17.78 0)
(length 5.08)
(name "D9"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "5"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at -5.08 20.32 0)
(length 5.08)
(name "D10"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "6"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at 25.4 5.08 180)
(length 5.08)
(name "D20"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "7"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at 25.4 7.62 180)
(length 5.08)
(name "D21"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "8"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin bidirectional line
(at 25.4 22.86 180)
(length 5.08)
(name "D0"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "9"
(effects
(font
(size 1.27 1.27)
)
)
)
)
)
)
)

4
pcb/sym-lib-table Normal file
View file

@ -0,0 +1,4 @@
(sym_lib_table
(version 7)
(lib (name "ledpcb")(type "KiCad")(uri "${KIPRJMOD}/ledpcb.kicad_sym")(options "")(descr ""))
)