Meta

I have been working on some games for the ESP32 and needed some decent quality audio with a minimum number of additional components. I was bouncing between using the DAC and using the I2S bus. The DAC requires less external parts, so I went that way. I ended up creating a very simple library for use in he Arduino IDE. (Note: This only works with ESP32)

DACs

The ESP32 has (2) internal 8 bit DACs. DACs are Digital to Analog Converters. You give them an 8 bit value and they output an analog voltage. The voltage range of the 0-255 8-bit value is roughly Gnd to 3.3V on the ESP32. If you digitize an audio file, you can then play it back through the DAC. The DAC can’t directly drive a basic speaker, but you can connect it to an amplifier or amplified external speakers. The 8-bit quality is not great, but more than good enough for simple games.

The sound data comes from wave (.wav) files. This uses the 8 bit, unsigned, uncompressed format. Wave files can be saved with any sampling rate you want. To get a decent sound you need to sample the analog files at thousands of times per second. I have found that 4000 Hz is about the minimum for anything musical or spoken. 8000 sounds pretty good for most stuff. For reference, CDs are sampled a 44100 Hz (also 16-bit not 8-bit). This means there is a lot of data even for short duration audio. The typical ESP32 board has 2 to 4MB. At an 8000Hz sampling rate that gives you 125 seconds per MB. That is plenty for what I am working on, so I decided to store the data on the ESP32. If that is not good enough, you could use an SD card.

Here is a reference of the wave format. Only a few of the values are used.

Byte

Length

Description

0

4

Always "RIFF"

4

4

File size in Bytes

8

4

Always "WAVE"

12

4

Always "fmt " with a null

16

4

Length of format

20

2

Audio format (1=PCM)

22

2

Number of channels

24

4

Sample rate

28

4

Byte Rate

32

2

Block Align

34

2

Bits per sample (8,16)

36

4

Alaways "data"

40

4

File size

44

...

Start of data

References

I found some good references to help me with this library.

IoT Sharing: This was a great reference for understanding the basics, but it uses an SD card to save the data.

I started with the Xtronical XT_DAC_Audio library, but found it got be very unstable when I added it to my game. It often crashed when seemingly unrelated code was added. I think the problem was due to trying to use floating point math in the interrupt. As soon as I took that out, it got very stable. They make reference to the issue in the code and suggest it could get fixed via compiler updates.

How it works

The wave data is stored in large char arrays. An interrupt reads the data and feeds that to the DAC. Using an interrupt allows the audio to play “in the background” while the game is running. The Xtronical library uses a fixed interrupt rate of 50kHz. It does some floating math in the interrupt to adjust to the actual sample rate of the wav file. I decided to change the interrupt rate to the actual sample rate of the wav data.

The sample rate is stored in the header of the wav data. When you play the file, it sets the interrupt rate to match the sample rate, so no math is required. You can use a mix of sample rates in the waves you use. It will adjust as needed before it is played back. It allows 2000Hz to 50000Hz sample rates. If you try to go outside that range it will use 2000 Hz. You will easily know there is a problem if you hear that.

Game Related Features

I added some features that might be needed when using with a game.

Check to see if the audio player is currently playing anything.

Interrupt The Current Wave – If something happens like an explosion you need to immediately switch to that sound. This is an option when you send a command to play a wave.

Change the Frequency – I had some sounds that needed to change based on game speed. There is an option speed up r slow down the play back speed by a multiplier to give.

Create a Game_Audio_Class object. The first parameter is the DAC pin number you want to use. It should be 25, 26. The second parameter is the timer number to use. Example: Game_Audio_Class GameAudio(25,0);

Create a Game_Audio_Wav_Class object. The only parameter is name of the char array of you wave data. Example: Game_Audio_Wav_Class pmDeath(pacmanDeath);

I recently bought some laser galvos from Aliexpress. What I got was the basic guts of a laser light show system. It came with everything I needed except the lasers. My goal is to control a laser to make a large interactive artistic display or game controlled by a micro controller with a DAC. I have a PSoC 5 and an ESP32 that have DACs, so I may use those.

Galvos work like speakers, old school analog meters or hard drive arms. They move proportional to a current. They can move extremely fast and precisely with the ability to move to 30,000 positions per second. The galvos came with drivers. This simplifies the control to a simple differential voltage. A differential voltage is used to increase noise immunity. The ILDA spec says the differencial voltage is 0 to 10V. This means at one end of travel you supply -5V and 5V and at the other end of travel you swap the voltages supply +5V and -5V.

My DACs are 0V to 5V (0r 3.3V). I need to convert this range to a 10V differential voltage. The easiest way for me to do this is to use some op amps. With what I have on hand it is easiest to get the 10V differencial using 0 to 10V and -10V to 0. I tested on the galvos by outputting a -10V to 10V sin wave from a function generator. It worked great.

Assuming I use the 0-5V DAC, I need to map that to a -10V to 10V range. That is a 20V span and requires a 4x gain. I then need to offset that by -10V. The op amp circuit I show below is what I made.

I used an LM324N because I had some. That has (4) op amps in a single package. The rails of the device need to be hooked up to a + and – supply that is greater than the range I will be using. Fortunately the galvos came with a power supply that outputs +15V and -15V. I used some potentiometers in the circuit to allow me to adjust the circuit.

The lower op amp provides the gain. The gain on the positive side is 1 + 30k/10k which is 4. The negative side is used for the offset and its gain is 30k/10k which is 3. I need an offset of 10V, so 10V divided by the gain of 3 is 3.33V. I need that value to come from the upper op amp. That op amp has a gain of 1 so I simply need to adjust the pot in front of that to output 3.33V.

The DAC is connected to the lower left voltage source in the schematic shown as 2.49V. The galvos would be connected to Gnd and the output of the lower op amp (green line). The schematic is interactive. Click the link below and try adjusting the input voltage between 0V and 5V.

Here are the signals on an oscilloscope. The yellow trace is the 0-5V input as a 5kHz sin wave. The blue trace is the output. Both traces use the center line as the 0V. The scale is 5V per division. The input has a low of 0V and a high of 5V. The output goes from -10v to 10v.

I am using the tiniest laser I could find so that I don’t have to worry about safety yet. I 3D printed a base to keep things in line.

Introduction

First…. Most of the credit must go to Robin Baumgarten and Critters for the inspiration and firmware. While I have hacked and tweaked the firmware a lot, the basic design is still all Critter’s. He did a great job.

A lot of people have asked me to help them build one, so this blog post is here to help them out. It is easy and fun to design and build your own parts and electronics. You can also either use my or Critters 3D printed parts.

The Electronics

The electronics are quite simple and only consist of a few basic pieces.

Arduino Mega – The firmware will not fit on an Arduino UNO, so you must use an Arduino Mega or anything using the the atmega2560 micro-controller. You can tpyically find a clone for less than $10.

MPU-6050 – This is a 3 axis MEMS accelerometer and gyroscope. The easiest way is to buy a GY-521 breakout board. You only need to use the VCC, GND, SCL and SDA pins. Note: My shield also has the INT pin, but that was for experimentation. You can find these breakout boards on Amazon for less than $5.

Speaker – You need a small standard speaker. The sound quality is not great, so don’t invest in anything expensive. I used an 8 Ohm speaker, but anything should probably work. The speaker is hooked directly to the Mega I/O, so you also need a 100 Ohm resistor in the speaker circuit. Typically a 1/10w to 1/4w resistor would be used. Note: This resistor is included on my shield. If you use my 3D printed design you will want a 40mm diameter with very little depth to it. Note: Do not connect directly to an amplifier. It is not designed for that.

LED Strip – The FastLED library that is used, supports a lot of types. I like the APA102C (Dotstar) type. I have also tested WS2812 (Neopixel) types. Most of the testing I did was on a 1 meter 144 LED APA102C strand and it looked great. The game gets difficult when there are less LEDs, so I would recommend at least 90. I have also tested with (2) 1 meter 144/m strips soldered together and a giant 5 meter 90 LED/M strip. They all look and work great. The firmware supports up to 1000. Most longer strips are soldered smaller sections. It is easy to solder strips together like the image below. Be sure the 5V, Gnd, etc. are aligned the right way. I have some strips that are waterproof. That is not required, but does not hurt.

Note: Do not power the LED strip directly from the Arduino. Power it separately from a power supply. Note: My shield has an input for this. It will also power the Arduino.

Power Supply – Technically, you could need upwards of 40mA per LED. I bought a 10A supply and it has worked fine without getting hot up to 450 LEDs.

Life LEDs – The firmware supports remaining “life” LEDs. I prefer to use the main LED strip for this. It is fun to live within the limitations of the LED strip as the sole display. Using the strip also allows you to adjust the life count in firmware. The default is 3 lives per level, but I have boosted it to 5 for testing. Note: My shield uses different I/O pins for the LED than the original TWANG firmware, so you need to check this if using them.

Wiring

The image below shows all the required connections to the Arduino Mega. My prototype used male header pins poked into the Arduino headers. It worked fine, but wires did often pop out when removing the cover.

The TWANG Shield

While hand wiring is very simple, I found it to be messy and I worried about failures. I made a basic shield to clean everything up. Here are the features of the shield.

LED Strip Terminal Block – It is very easy to hook up the strip. It works with both 3 and 4 wire strips. The power comes from the shield and no additional connections are required on the strip. Connections are clearly labeled. 3 wires LED strips do not use the CLK connection.

Accelerometer Terminal Block: This has clearly labeled connections using the same names that are on the MPU-6050 accelerometer module. Just hook them up 1 to 1.

Speaker Terminal Block: This also has 5V and Gnd if your hacking requires these connections. The 10 Ohm speaker resistor is mounted on the board.

Main 5V power entry connector: This powers the LED strip. It also powers the Arduino. It uses a diode so you can also power the Arduino via USB for programming.

Arduino UNO compatible: While the default firmware will not fit on an UNO, future compact version might be possible.

Life LEDs – My enclosure does not use them, but you could wire some in. The resistors are included, but not the LEDs. You could solder LEDS on the board or remotely locate them and solder wires to the PCB.

The Firmware

All of this is fully compatible with the original TWANG firmware. I forked the original and added a few changes. I would be happy to merge back to the original some time in future. The firmware relies on several libraries. Follow the instructions on GitHub pages to get those libraries.

Observations and Feedback.

It’s difficult to beat. Only one person got all the way to the boss level and defeated it. Amazingly, it was Elan Lee. He loved the game and gave me some good ideas to work on.

Most people got killed in the second to last level. It has a lot of enemies and a conveyor that keeps pushing you back to the bottom. There is also a sneaky enemy spawner at the bottom that gets a lot of people. It is a great level, so I don’t want to remove it. I have added a few more levels before it to practice before that.

The Lava Pools. The lava pools confused some people. I changed the pools to look more red, flickering and scary when they are on and less scary when off. To me it looks more obvious now what to do.

The Sound. I love the chip tune style sound out of the Arduino, but it needs to be way louder. In a large crowd, you cannot hear it at all. I think it needs an amplifier or an option for an external speaker.

Boss Level: By design, the exit at the top of the boss level does not appear until all bosses are dead. People did not understand this and tried to exit out the top early, because the boss respawns below you after the first “kill”. That caused the players to try to leave the game without ending the level. If you exited the top in this mode, the player disappeared without a way back. This is very annoying if you get all the way to this last level. I fixed the code so you can’t goes past the second to last LED when the boss is still alive.

New Features: I asked several people for new ideas. I got some to work on, but already added one. The attack width is now adjustable. It will default to the old width, but you can change it per level.

More levels. A typical game lasts about about 1-2 minutes. I think a few more medium difficulty levels would help.

Scoring System: It would be cool to know how you did compared to others. It could display the score as a bar on the strip, with the max possible being the full length. You could then mark your level somehow by the strip. (Postit note flag, dry erase pen, etc)

Next Steps

Release all the source files.

Firmware: I have been hacking the code quite a bit. I’ll release my changes after some clean up and testing.

STL files: I have been using odd sized speakers harvested from some cheap external speakers. When looking looking to buy some, it seems like 40mm diameter is a good standard size that is cheap and available. As soon as I get some and test them, I will release the files for this size.

Sell on Tindie. My shield makes wiring super easy, but is definitely not required. I think I’ll sell everything, except for the Mega and LED strip. I’ll also just sell the assembled PCB by itself.

New Hardware:

Raspberry Pi Zero W: I have looked into several hardware options and this seems to be a good candidate. I think it will be a simple way to get good audio and connectivity. I have the accelerometer and LED strip working so far. The audio will be an I2S amp chip that will be put on a shield. The (2) drawbacks are boot time (20-30 second) and you are probably limited to APA102C (dotstar) type LED strips. Edit: I got a good portion of the code on the Pi running. It runs fine, but I don’t like the requirement for a slow and controlled shutdown of the Pi. It would require a button and some sort of visual feedback.

While the my TWANG clone has been running great, I wanted to clean up the wiring, so I made a shield to plug into the Arduino. I previously used header connectors plugging into the Arduino. The connectors go to three different places and come from all over the Arduino , so there were a lot of connectors including some single pin ones. I was worried they might pop out or fail. I also had to externally power the LED strip and supply power via USB to the Arduino.

The shield takes care of all of this and groups all of the external connections by function on easy to connect and clearly labeled terminal blocks. Here are the features I have…

Single 5V Power Connector: This connector powers the LED strip via a very heavy trace on the PCB. It also powers the Arduino. The Arduino is powered through a Schottke diode. If you plug in the USB, the Arduino switches to be powered by the USB. This allows you to program and hack the firmware while the LED strip is powered.

Terminal Block Connections: The wires are grouped by peripheral (Accel, Speaker, LED Strip) and clearly labeled.

LED Strip Connections: This powers and controls the LED strip. I have tested it with 4 wire (APA102, Dotstar) and 3 wire (Neopixel) strips.

Speaker Connection: There is an integral 100 Ohm resistor that is required when you directly power the a speaker from an Arduino. The terminal block also has 5V and Gnd in case you want to add a simple amplifier. BTW: Driving the speaker directly from the Arduino is plenty loud in my opinion.

Shield Size: The shield will work on both an Arduino Mega sized board or an Arduino UNO sized board. The TWANG firmware requires the extra memory of the Mega, but a tiny, reduced feature, UNO version could probably be made.

Life LEDs: There are provisions for 3 LEDs that are typically used to show remaining lives. I have not been using those. I prefer to use the LED strip to show remaining lives. I like working with the restriction of a 1D LED strip display.

Prototype Assembly Notes: I did not have all of the correct parts for the build. I did not have a 100 Ohm SMD part, so I tacked on a through hole part. I did not have the right terminal blocks, so I cut one and only used 3 positions for the speaker. The correct parts will arrive soon.

Here are some more images.

Future Changes

I will probably get rid of the life LEDs.

I will add a large capacitor for sensitive LEDs, like Neopixels. Right now I just connect the cap to the terminal block.

I will probably sell the rest of this batch on my Tindie store in a week or two. I will probably sell assembled boards and full assemblies (less LED strip and Mega)

I have been a Patron of Robin Baumgarten for a while. He makes experimental hardware for games. His Line Wobbler one dimensional dungeon crawler is my favorite and I have always wanted to play it. It uses a door stop spring as the controller. An accelerometer in the knob allows it to work like a joystick and also detect the wobble used to attack the enemies.

Original Line Wobbler (Robin B.)

After seeing his playable Christmas tree version of the game, I had to make one for myself. I could not find any source files that he published, but I was able to find an open source clone called TWANG. The game is quite fun and surprisingly challenging.

Original Twang Version

Electronic Hardware

Here is a list of the electronics hardware used.

Arduino Mega. The Mega is way overkill for the I/O requirements, but an UNO does not have enough memory.

MPU-6050 3 Axis Accel/Gyro Breakout Board. These are available for about $5 and have good library support for Arduino.

Small Speaker. I bought a pair of external PC speakers at Micro Center for $4 and pulled out some 2″ speakers. You need to use a 100 Ohm resistor on one of the wires.

RGB LED Strip: The default code is written for the APA102 type strips. The FastLED library used also supports the cheaper WS2812 (Neopixel) strips. I used a 144 LED 1 meter APA102 strip. The Clock and Data type strips can work faster and they typically have an overall brightness factor that gives them a more useful brightness range than Neopixels. The brightness of these strips is insane and you typically run them at about 1/2 brightness.

Life LEDs: You can use 3 individual LEDs to indicate the number of lives you have left. I decided to skip that. I preferred the simplicity of a signal display element. I added a game over animation to the game to make it more clear that you are dead, dead.

Printed Parts

I created my own 3D printed parts. I was having trouble with the TWANG Thingiverse files. They are OBJ files and the parts are grouped. Cura was not creating good prints. My speaker was not going to fit anyway.

Chassis: I made a heavy walled enclosure to give it a little weight and make it extra strong.

Cover: The cover is also very thick. The speaker mounts in a pocket and is attached with hot glue.

Spring Clamp. This holds the spring to the cover securely. I also added a little hot glue to prevent it from rotating.

Knob Base. This is very similar to the official TWANG version. It has a longer, threaded interface to grab the spring. This parts takes a lot of abuse.

Knob Top: Snaps on, but also gets a little hot glue.

The Firmware

The firmware is well written and pretty easy to follow. You need to download a lot of libraries. Some can be installed from the Arduino IDE and some must be downloaded manually. This is pretty well explained on the Github page.

Everything works on a 60 frames/second loop. This includes the display and the sound. I was able to tweak a few things easily and add a game over animation.

The levels are very easy to edit. You really don’t need to know how to program. I tweaked a few to make them easier for beginners.

Put a little hot glue around the spring where the clamp goes. Screw it down.

Attach Speaker to Cover

Blah

Attach some wires. Put a 100 Ohm, 1/4W inline on one of the wires.

Assemble Base

Install the Arduino Mega into the base with screws.

Connect all the wires per the graphic below. I wired the accel SCL/SDA at the left end, but you can also wire them to pins 20 & 21 at the right end.

Attach Cover

Usage

You need to power the LED strip with a separate 5V power supply. I used a 10A supply for my 144 LED strip.

You also need to power the Arduino. The easiest way is to do it via the USB port. You could wire the power supply in the first step to the 5V on the Arduino, but be careful to never power from the power supply and the USB at the same time or something will likely break.

Note: I have been hooking up the LED power first. When I only power the Arduino, I see some flickering of LEDs. That concerns me that it is drawing some power from the I/O pins.

Next Steps.

Make it Easier to Build: The wiring is a pain and probably not too durable. I used pins crimped into connectors that mated to the Arduino Mega. To make it easier I designed a little shield with screw clamps. It will also power the Arduino through a diode that will allow the USB to also be used. The speaker resistor is part of shield. It is also compatible with an Arduino UNO, so a pocket sized TWANG might be possible. That arrives next week. I will likely sell the extras on Tindie.

ESP32 Version: I would really like to try this. The sound and speed should be better and the ability to network with another player sounds cool. It is also smaller and cheaper.

Scoring System: Everyone want to compete.

Video

A lot of people have asked about building their own Coasty Laser Cutter. It takes a lot of work to get the files ready for release. I will release the source files in stages as they are ready so people can get started. Watch this post for updates. Subscribing to this blog or following me on Twitter (@buildlog) is a good way to keep up.

When everything is ready, I’ll probably also post on Thingiverse.

3D Printed Parts

Here are the STL files for the 3D printed parts. The parts are generally pretty easy to print. They require no support and can be printed in low resolution. I print at 0.28mm layer height. You need to watch out for warping on the chassis and front door. If the chassis warps it will stress the PCB and could damage some parts. The door needs to be flat in order to close properly.

I printed my parts in generic PLA. They printed fine, but if you have some crappier PLA or if you don’t have a heated bed, you should probably print with a brim. I would suggest printing the chassis first. If you can print that, the other parts are easier. I have some PETG on order to test. That supposedly warps less that PLA.

The holes used for the 8mm rods are designed to be a press fit. If the rods are hard to install, try cleaning the holes up a little by hand with a 5/16 or 8mm drill. The drive shaft bearing is also a tight fit. Try using a vise or clamp to press it into the chassis.

I have receive a lot of requests to sell Coasty laser cutters. It just is not practical for me to do this at this time, but the parts are easy to buy and/or print yourself. The only part that is difficult is the custom controller. I have about 10 extra ones and will sell them. If they go quickly I may buy more. They are here in my Tindie Shop.

What you get with the controller.

(2) TI DRV8825 stepper motor drivers with heatsinks and the current set to a recommended value

(2) Fans with wires trimmed and connectorized.

A cable for the laser module

A door switch switch with proper length wires and connector.

These are the only electronic items you need to provide.

Laser Module: It is designed for the Eleksmaker 3.5W LA03-3500. Most other types probably won’t fit in the tight size of the Coasty or bolt properly to the PCB

12V Power Supply: I recommend about 5A of current. They can be found on Amazon for less than $10. Make sure it has a standard barrel connector end.

Default Calibration

The controller will come setup with settings that work for me. You can fine tune the settings later, but these should get you started. Here are the settings you see if you send the $$ command to Grbl. The setting codes are listed here.

The homing switches locate the edge of the coaster and the left extent of the laser travel. This is not the X,Y zero of the work area on the coaster. That is set by the G54 work offset. The G28 and G30 locations are also set so they can be used as a coaster eject command. Here are the offsets you will see if you send the $# command.

Note: If you want to reset the G54 to the value above send this command G10 L2 P0 X-186.500 Y-245.000 Z0.000 For more information regarding work offsets see this video. You could also manually jog the machine to the exact position you want the 0,0, to be and send this command G10 L20 P0 X0 Y0 Z0

Testing

I will pre-test every controller, but there are many machine dependent things that need to be tested before safely operating the machine. You should only need to run these tests once.

Remove the Bluetooth Module. It will be easier to test with USB. Never use USB with the Bluetooth Module installed.

Do not connect the external power supply until advised.

Make sure the little power push button switch on the controller is in the off (out) position. This switch controls the laser and fans only. Other circuits remain on regardless of switch position.

Connect a USB cable.

Open a serial terminal connection at 115200. The terminal should be setup to send a carriage return at the end of each line. The Arduino IDE Serial Port Monitor is an easy terminal to use.

It should reply with Grbl 1.1f [‘$’ for help] and [MSG:’$H’|’$X’ to unlock] when connected

Send a question mark ?

It should replay with some status like <Alarm|WPos:186.500… , but not have any switch status like Pn:…

Send the $$ command.

The values in the response should match the values listed in the calibration section above.

Send the $# command

The replied values should match the values listed in the calibration section.

Connect power to the controller, but do not turn on the controller’s power switch. Be ready to pull the plug if anything goes wrong. The machine might make some motor noises as the motors engage for brief period.

Open the door.

Manually slide the laser carriage to the left to activate the X home switch. While it is activating the switch send ? again.

You should see Pn:X in the response.

Block the IR detector with a coaster and send ? again. Note: The IR detector requires external power and will always register as “on” when there is not external power.

You should see Pn:Y in the response

The next step is to test homing. There is a chance that it will home the wrong way, so be ready to disconnect power. You must pull the plug at the controller to fill power. Watch for the laser to move to the left and the coaster to move in.

Send the $H command at the serial terminal.

As soon as the motors start, watch for the laser to move to the left and you should feed in a coaster.

If either go the wrong way, pull the plug. See fixing direction errors below.

The machine will only try homing for a few seconds. If you were unable to get it started in time, try $H again.

If the coaster does not run smoothly you might need to sand the track a little.

After a successful homing, send G1 X0 Y0 F400

The machine should move so the laser is over the lower left corner of the coaster.

Send G28 to eject the coaster. Remove it completely from the machine.

Close the door and screw it shut.

Turn on the laser with the push button. You should hear the fans turn on, but the laser should not fire.

You will now test fire the laser. You only want to test fire it for a should period of time at low power. Send the following commands. While the power will be low, do not leave it on for more than a second or 2.

$X (this will make should the machine is not in alarm mode)

G91 (this will allow you to move it in incremental mode)

S10 (This will set the beam power to 1%. Full power is S1000)

G1 X3 F400 (This will move the laser 3mm to the right. The primary purpose is to put the controller into g1 mode where we can turn on the laser)

M3 (should turn on the laser. It will not be very bright.

M5 (turn it off)

Assuming all tests passed, the machine should be ready to use.

Fixing motor direction Errors

The easiest way to fix direction errors is to rotate the connector for the problem motor by 180°. The upper motor is for the X (the laser carriage) and the lower motor moves the coaster.

Rev 2.0 PCB Issues

There was one mistake on the PCB due to net naming issue. The 12V input did not get connected to the 12V to 5V DC power supply. A small rework wire has been added on the back side of the PCB.

New Traction Roller

I made the traction roller diameter a lot smaller and moved it behind the beam. A smaller roller has a lot of advantages. It allows the beam to be closer to the contact points of the rubber orings. This improves the usable work area, because you can get closer to the edge of the coaster. With a smaller diameter the coaster travels less per revolution. This increases the torque and resolution.

Smaller Chassis

The chassis is now about 16mm smaller in depth due to the smaller roller and new location. The depth of the machine is quite a bit smaller than the coaster.

Fan Guard and Carbon Filter

I added a fan cover on the back. This acts as a finger guard and also allows a few layers of carbon filter cloth to be used. Bulk carbon filter cloth for use in air purifiers can be purchased on Amazon very cheaply. It removes a good portion of the odor of the smoke.

Carbon Filter Cloth

Door Interlock Switch

There is now a switch that cuts all power to the laser when the door is opened. You can still run the machine to test the motors, homing etc, the the beam cannot turn on with the door open.

IR Coaster Detector

I was not happy with the coaster homing switch used on the first version. While it never failed, it did not appear to be very robust and it caused some drag on the coaster. I changed to a IR LED and photo diode. When the light from the LED hits the photo diode, it conducts to the +5V. When the coaster blocks the light, it is pulled down to ground. I used a pot on the pull down because it did not know what he exact value would be. It turns out the value needs to be about 40k. The only catch was the microcontroller input pin pull up resistor on the Nano could not not used because it is less than the 40k. This required a slight hack to Grbl because Grbl is all or nothing on the pull ups for the limit switches.

I was not sure if ambient light changes might be a problem, like bright sunlight. The photo diode looks down and that appears to be good enough to avoid overhead light. I also have a mounting screw there in case I need to add a little shade/cover.

IR LED / Photo Diode Circuit

Bluetooth

I have been using Bluetooth on some other machines and really like it. Skipping USB cords and using a phone instead of a computer is great. I have found it to be very reliable. The real world bandwidth appears to be a little lower than 115200 USB. It has not been a problem, but I don’t do much gray scale engraving on this machine which needs higher bandwidth. Regardless, USB is still an option.

Well that was easy! About an hour ago I wrapped up a blog post on creating stepper motor driver pulses with the ESP32 using timer interrupts. I added a to do list at the end to look into using the RMT peripheral to do this. It only took about an hour to figure out.

RMT stands for “remote control”. It was designed for things like an IR remote control where tight timing on GPIO is required. The peripheral has a lot of features that make it good for a lot of things. Some people have been using it for the notoriously tight timing of the NEO Pixels.

The documentation is pretty complete on the API, but there are very few examples and tutorials. Most that do exist are for complicated things and not too well commented. This Ebook by Neil Kolban has a good example that my code started from. Look for the section called “RMT – The Remote Peripheral”. Due to my limited knowledge of the RMT, I will only go over my implementation.

Basically you start with two structures…(also see code below)

rmt_config_t config;

This is used to setup the configuration. I set config.clk_div = 80 so that each unit of time in my setup is 1us.

rmt_item32_t items[1];

This is an array of items that represent the outputs transitions that you want. In my case I only want a transition to high for 3us and then transition to low with no duration . Here is the definition of that struct.