Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional LED Ring Mod #15

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ A video covering most of this information can be found at https://www.youtube.co



## Optional Mods ##

* [LED mod](./mods/led_ring/README.md)


## License ##

Copyright (C) 2018 Andrew Tait <[email protected]>
Expand Down
5 changes: 5 additions & 0 deletions mods/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SC mods

Optional modifications for the SC

* [LED Ring Mod](./led_ring/README.md)
64 changes: 64 additions & 0 deletions mods/led_ring/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# LED Ring mod for SC

This is an optional modification to add a LED ring to display the current platter position, like having a sticker on vinyl.

[![Demo Video](https://img.youtube.com/vi/FGX4gD_Zo5w/0.jpg)](https://www.youtube.com/watch?v=FGX4gD_Zo5w)


Required hardware:

* **ESP8266** (~$5)

Used a dev board for easier development, but plain ESP chip should work too.

* **LED ring** (WS2812 aka Neopixel, ~$10)

The more LEDs the ring has, the more precise the angle can be displayed. Tested with 24 LEDs (15°/LED).

Depending on your case: maximum diameter of ~10cm to fit into the default case.

This mod will also work with an LED strip, it doesn't have to be an actual ring.

[Supported protocols](https://nodemcu.readthedocs.io/en/release/modules/ws2812/): WS2812, WS2812b, APA104, SK6812 (RGB or RGBW)


## Steps

* Flash the NodeMCU firmware, see [./firmware/README](./firmware/README.md)

* Upload the LUA software, see [./software/README](./software/README.md)

* Connect the hardware

```
┌──────────┐
│ ESP8266 │ ┌───────────────┐
├──────────┤ │ WS2812 (LED) │
¦ .. ¦ ├───────────────┤
┤ D4 ├-------------┤ IN │
┤ 3.3V ├-------------┤ VCC │
┤ GND ├-------------┤ GND │
¦ .. ¦ └───────────────┘
┤ RxD0 ├----┐ ┌───────────────┐
┤ TxD0 ├ | │ J7 (SC1000) │
┤ GND ├----+---┐ ├───────────────┤
┤ 3.3V ├-┐ │ └--┤GND 3.3V ├-┐
└──────────┘ | | ┤UART3 RX ├ |
| └------┤UART3 TX ├ |
| ┤ ├ |
| ┤ ├ |
| └───────────────┘ |
└---------------------------┘
```


* Enable the mod in `settings.txt`

```ini
# 1 to enable LED ring mod, default 0 (disabled)
ledringenabled=1
```

* [Optional] Configure the LED color and pattern

See [software/README](./software/README.md)
37 changes: 37 additions & 0 deletions mods/led_ring/firmware/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Firmware for the ESP8266

Using LUA based NodeMCU firmware: https://nodemcu.readthedocs.io/en/release/


## Download firmware

Use the provided `./nodemcu-1.5.4.1-final-14-modules-2019-12-31-14-52-16-float__adc_file_gpio_http_i2c_net_node_rtctime_tmr_u8g_uart_wifi_ws2812_tls.bin` firmware.

Or build and/or download your custom firmware:
* Docs: https://nodemcu.readthedocs.io/en/release/build/
* Cloud build: https://nodemcu-build.com/


This project requires the following modules: `file gpio net node tmr uart ws2812`


## Flashing firmware

Easiest way is to use the python-based [esptool](https://github.com/espressif/esptool).

`pip install esptool`

`esptool.py --port /dev/ttyUSB0 write_flash 0x00000 ./nodemcu-1.5.4.1-final-14-modules-2019-12-31-14-52-16-float__adc_file_gpio_http_i2c_net_node_rtctime_tmr_u8g_uart_wifi_ws2812_tls.bin`
(Adjust the USB port to your actual one)


During next boot after successful flashing, the ESP should display a message similar to:
```
NodeMCU custom build by frightanic.com
branch: 1.5.4.1-final
commit: b9436bdfa452c098d5cb42a352ca124c80b91b25
SSL: true
modules: adc,file,gpio,http,i2c,net,node,rtctime,tmr,u8g,uart,wifi,ws2812,tls
build created on 2019-12-31 14:51
powered by Lua 5.1.4 on SDK 1.5.4.1(39cb9a32)
```
Binary file not shown.
83 changes: 83 additions & 0 deletions mods/led_ring/software/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Upload the software to ESP


* Adjust `config.lua` to your needs

**Depending on the LED ring (or stripe):**

```lua
-- Number of LEDs
LED_COUNT = 24

-- 3 for RGB strips and 4 for RGBW strips
BYTES_PER_LED = 3
```

**Debug mode:**

When active, the ESP will generate a _fake_ rotation signal by itself for demonstration and development purpose.

```lua
-- Enable demo signal to show a hard coded LED rotation (0|1)
DEBUG = 1
```

* Adjust `pattern.lua` to your needs

**The light pattern:**

Depending on your preferences how to use stickers on real vinyl (some people use 1, some people use multiple markers), you can adjust the light pattern.

```lua
-- LED patern (list of LED positions to use)
--
-- Format:
-- { {angle_offset=0, r=0, g=0, b=255}, {angle_offset=180, r=255, g=0, b=0} }
--
-- Values of single item:
-- angle_offset (0..359): 0 = current position
-- r, g, b (0..255): color value for R, G and B
PATTERN = {
{angle_offset=0, r=0, g=0, b=255},
{angle_offset=120, r=255, g=0, b=0},
{angle_offset=240, r=255, g=255, b=255},
}
```

This example pattern uses 3 LEDs in parallel to mark 0°, 120° and 240° (like the Mercedes star):
* 0° (the actual position): bright blue
* 120°: bright red
* 240°: white


How to calculate the possible angles:

In this exmple, we use a LED ring with 24 LEDs, which results in 15°/LED (360°/24=15°). LED positions start at 1 and angles are integers.

| LED position | Angle range |
|:-------------:|:------------:|
| 1 | 0..14° |
| 2 | 15..29° |
| 3 | 30..44° |
| .. | .. |
| 24 | 345..359° |


* Upload all `*.lua` files to the ESP

e.g. with [ESPlorer - IDE for ESP development](https://esp8266.ru/esplorer/)

* Reboot


## Concept

The ESP will listen to and execute RPC commands directly from serial port (UART 0).

The main method is to set the rotation angle and control the LEDs accordingly to visualize this rotation angle.

To trigger it, send the following string with the `angle` as an integer of the current rotation (in degree from 0..359):
```lua
r(angle)\r\n
```
_This is exactly what the SC will send via UART3(J7) later._
18 changes: 18 additions & 0 deletions mods/led_ring/software/config.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-- LED ring (ws2812) --------------------------

-- Number of LEDs
LED_COUNT = 24

-- 3 for RGB strips and 4 for RGBW strips
BYTES_PER_LED = 3



-- Debug mode ---------------------------------

-- Enable demo signal to show a hard coded LED rotation (0|1)
DEBUG = 0



-- Hint: See pattern.lua to configure the LED pattern
26 changes: 26 additions & 0 deletions mods/led_ring/software/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
local boot_delay = 5 -- in sec; allows recovery when script goes crazy

function init_real()
tmr.stop(0)
dofile("config.lua")
dofile("pattern.lua")

-- Init ws2812 LEDs
print("[INIT] WS2812 ("..LED_COUNT.." LEDs) ..")
ws2812.init()
led_buffer = ws2812.newBuffer(LED_COUNT, BYTES_PER_LED)
led_buffer:fill(0, 0, 5) -- all LEDs soft blue to show it's initialized
ws2812.write(led_buffer)
dofile("led.lua")

-- Init serial port to receive RPC calls
local uart_id = 0 -- only UART 0 is capable of receiving data
local echo = 1
uart.setup(uart_id, 115200, 8, uart.PARITY_NONE, uart.STOPBITS_1, echo)
print ("[UART] Config", uart.getconfig(uart_id))

wifi.setmode(wifi.NULLMODE)
end

tmr.alarm(0, boot_delay*1000, 0, function() init_real() end)
print("Boot delay ("..boot_delay.."s) ..")
27 changes: 27 additions & 0 deletions mods/led_ring/software/led.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
led_buffer:fill(0, 0, 0);
local degree_per_led = 360 / LED_COUNT

function _angle_to_led_pos(angle) -- returns index of LED (1..LED_COUNT) by angle in degree
angle = angle + math.ceil( -angle / 360 ) * 360 -- normalize angle to 0..359
pos = math.ceil((angle+1) / degree_per_led)
return pos
end

function r(angle)
-- Set new rotation position (angle= 0..360°).
-- Triggered via direct RPC from serial port.
led_buffer:fill(0, 0, 0);
for i = 1, #PATTERN do
led_pos = _angle_to_led_pos(angle + PATTERN[i].angle_offset)
led_buffer:set(led_pos, PATTERN[i].g, PATTERN[i].r, PATTERN[i].b)
end
ws2812.write(led_buffer)
end


if DEBUG == 1 then
print "[DEBUG] Demo mode with fake rotation signal."
local debug_tmr = tmr.create(); local debug_angle = 0; local debug_angle_step = 5
debug_tmr:register(20, tmr.ALARM_AUTO, function (t) debug_angle = debug_angle + debug_angle_step; debug_angle = debug_angle + math.ceil( -debug_angle / 360 ) * 360; r(debug_angle) end)
debug_tmr:start()
end
13 changes: 13 additions & 0 deletions mods/led_ring/software/pattern.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-- LED patern (list of LED positions to use)
--
-- Format:
-- { {angle_offset=0, r=0, g=0, b=254}, {angle_offset=180, r=254, g=0, b=0} }
--
-- Values of single item:
-- angle_offset (0..359): 0 = current position
-- r, g, b (0..255): color value for R, G and B
PATTERN = {
{angle_offset=0, r=0, g=0, b=255},
{angle_offset=120, r=255, g=0, b=0},
{angle_offset=240, r=255, g=255, b=255},
}
81 changes: 81 additions & 0 deletions software/DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Development setup

_DISCLAIMER: This developer help was written with very limited beginner knowledge in all these topics. Take it with caution!_
_I figured out all this by try and error and i'm sure there are better ways of doing it. Still hope this helps someone who wants to tinker around in the future. Corrections appreciated. – @psturm_


## install buildroot env

As preparation, create ARM buildroot to be able to compile for the SC..

```sh
# download and unpack
wget https://buildroot.org/downloads/buildroot-2018.08.4.tar.gz
mv ./buildroot-2018.08.4.tar.gz /opt
cd /opt
tar xfv buildroot-2018.08.4.tar.gz

# prepare config & overlay
cd <SC1000_PROJECT_PATH>
cp ./os/buildroot/buildroot_config /opt/buildroot-2018.08.4/.config
cp -R ./os/buildroot/sc1000overlay /opt/buildroot-2018.08.4/

# build
cd /opt/buildroot-2018.08.4/
make # takes some time ..
```


## build `xwax`

Requires a buildroot environment (see setion above).

To build the `xwax` binary from source:

```sh
cd ./software

# Adjust path in Makefile to your buildroot:
# CC=/opt/buildroot-2018.08.4/output/host/usr/bin/arm-linux-gcc

make clean && make xwax
```

In my case, this still created wrong paths in the binary. As a quick fix, i created a symlink `/root/buildroot-2018.08.4 -> /opt/buildroot-2018.08.4` and used this in Makefile: `CC=/root/buildroot-2018.08.4/output/host/usr/bin/arm-linux-gcc` (there are better ways to do this for sure).


## debugging SC1000

Needs a USB-TTL-serial-converter to connect to UART of main processor on the SC1000.

Check "6.1.1 UART1 interface" in https://www.olimex.com/Products/SOM/A13/A13-SOM-512/resources/A13-SOM-um.pdf (page 24)

Hint: don't forget to cross RX & TX!

To connect:
`screen /dev/ttyUSB0 115200` (Adjust the USB port to your actual one)

or maybe use `GtkTerm`


## DeviceTreeBlob (dtb)

To change hardware mappings (e.g. PIN layouts)

```sh
cd ./updater/tarball/

# binary -> source
dtc -I dtb -O dts sun5i-a13-olinuxino.dtb > sun5i-a13-olinuxino.dts

# Change the source file to your needs

# source -> binary
dtc -O dtb -o sun5i-a13-olinuxino.dtb -b 0 sun5i-a13-olinuxino.dts
```



Customized DTS for the LED Mod:
* Remove power LED on PG9
* Enable uart3 (RX:PG9, TX:PG10), results in `/dev/ttyS1` on SC1000 (see `led_mod.c`)
1 change: 1 addition & 0 deletions software/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ OBJS = controller.o \
device.o \
dummy.o \
external.o \
led_mod.o \
player.o \
realtime.o \
rig.o \
Expand Down
2 changes: 1 addition & 1 deletion software/README
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SC1000 Xwax - xwax butchered to work with the SC1000 digital scratch instrument



See DEVELOPMENT.md for hints for local development.
Loading