Introduction: Arduino Laser Show With Real Galvos

In this project we use an Arduino UNO/Nano to run a laser show with a laser pointer. We are using real galvos (galvanometers) like in commercial laser projectors, since these have become quite affordable recently (around 100 Euros/Dollars) and provide a much higher quality than speakers or stepper motors.


On the hardware side, we build the Arduino driven projector by using a external 12Bit DAC (digital to analog converter) and an (optional) amplifier circuit to create the signal for the galvonometers.

You can build this project if you have some basic experience with an Arduino board and a breadboard.You can get away without any soldering, although it is probably a better solution to solder a PCB finally.


On the software side, a complete Arduino sketch is provided which features:

  • Text rendering (including zoom/translate/rotate)
  • Logo rendering
  • Drawing effect (draw object or text incrementally)
  • Line clipping
  • Optimized for small program size (PROGMEM font/objects) and speed (fixed-point arithmetic)
  • And a 3D cube that is rendered live...

All source code is provided and can be easily adapted to create your own show!

Inspiration / further reading

I was originally inspired by the following project, which explains quite well how laser projectors work and which uses speakers to simulate the galvos:

Using speakers is very limited regarding quality and complexity of the objects you can draw, which is why we use real galvos in our project.

Step 1: Parts You Need

Picture of Parts You Need
  • an Arduino UNO / Nano (or a compatible clone) + USB power
  • 20Kpps galvos with driver cards and power supply (these typically come in a set, see below)
  • a 220V or 110V power cord (if galvo power supply does not come with a cord)
  • MCP4822 DAC (a cheap dual channel 12 bit DAC)
  • a red laser pointer
  • some crocodile/alligator clips (to easier connect the laser pointer)
  • a breadboard or prototyping PCB
  • jumper wires
  • some Lego bricks (optional, for the laser mounting)
  • a box/casing to mount the project (optional but recommended)

If you want to build the (optional) ILDA amplifier, see the parts list in the amplifier step.

The most expensive parts of this project are the 20Kpps galvos. I bought my set on ebay:

Just search the internet / ebay for "20Kpps galvo" and you should find an adequate set. These sets typically come with a bipolar power source (mine uses +15V/-15V, if yours is in the range of 12-15V it should not make a difference).

Step 2: Laser Pointer

Picture of Laser Pointer

Hacking the laser pointer

For our project, we need to switch a laser pointer on/off from the Arduino. For this, you need to buy a cheap red laser pointer. It will typically have an on/off push button, which you need to fixate to a permanent pushed state. On my pointer, I just used duct tape to permanently press the button. Next you need to remove the battery case (back part of the pointer) and add power supply wires instead of the batteries. The easiest will be to use two alligator clips, typically one on the spring (-) and one on the case (+).

Have a look at the images for an example laser pointer.


To test the pointer, you can connect it like this: Arduino 5V -> Laser+, Arduino GND -> Laser -

If your laser pointer draws too much current to be safely connected to the digital output of the Arduino, you have to use a transistor or MOSFET to switch it. My pointer worked without problems, so it probably draws less than 50mA.


The pointer needs to be at the correct height to point into the galvos, for this you need to build some holder. I used some Lego bricks to build the holder, see above picture. Of course you can use any other material to build it.

Step 3: Setting Up the 20 Kpps Galvos

Picture of Setting Up the 20 Kpps Galvos

The galvo set should consist of:

  • The two X/Y galvos with mirrors (attached to a metal block)
  • Two identical driver boards, on for X and one for Y
  • A power supply
  • Connector cables to wire everything
  • Extra input connector cables

Power supply

In my set, the power supply did not have a power cord, so I added a standard 3 wire power cord (I used an old PC power cord and removed the PC connector). Be careful when you work with the power supply, since it works on AC 220V/110V and this is (as you should know) DANGEROUS! I recommend that you get some kind of box to mount everything in and reserve an extra isolated spot for the power supply. I glued a plastic box on top, covering the power supply so that nobody can touch the high voltage input.

Connecting everything

Now connect the cables from the power supply to each driver card and each driver card to one of the galvos. You should have two remaining connector cables, which you can plug into the ILDA input of each card. You can either use these connector cables or instead you may use individual female jumper cables instead. In the next step, we will connect these to the Arduino / DAC outputs.

Step 4: Wiring the DAC and Laser Pointer

Picture of Wiring the DAC and Laser Pointer

For this project we choose the MCP4822 DAC (as PDIP-8, to be breadboard friendly). It is available for 3-4 euros. It offers dual channel 12bit and there is an Arduino library available for it. It is connected to the Arduino via SPI and supports an additional LATCH pin which offers synchronous update of both channels. It will generate two output signals ranging 0V to 4.096V.

The following links to the datasheet for the DAC:

The wiring is done like shown in the images above.

The laser pointer is connected to GND and to Arduino pin D5. As said before, if you want to be on the safe side regarding drawing current from the Arduino, you can also use a transistor/MOSFET instead of a direct connection from pin D5.

The connection to the DAC is as follows:

Arduino CLK (pin D13) -> DAC SCK (pin 3)

Arduino MOSI (pin D11) -> DAC SDI (pin 4)

Arduino CS (pin D10) -> DAC CS (pin2)

Arduino pin D7 -> DAC LATCH (pin 5)

Arduino 5V -> DAC VDD (pin 1)

Arduino GND -> DAC VSS (pin 7)

This leaves us with DAC pin 6 and pin 8 which provide us with the two analog output signals.

One output of the DAC is connected to the ILDA driver card for the X galvo and the other one to the Y galvo. Since the ILDA driver cards expect a bipolar signal, in pricipal we would have to generate a signal from -5V to +5V and an inverted signal for the negative driver input. But these driver cards do not care so much about the bipolar signal, so you can wire each DAC output (with is positive 0 to +4.096V) to the ILDA IN+ connector and connect both the ILDA GND and ILDA IN- to the Arduino's GND. This will not drive the galvos to their full angle range, but it should already generate an image in about 1/4 of the galvos range. In a later step, we will learn how to create a correct bipolar signal.

In principle, this DAC is replaceable by any other dual channel DAC
that operates on 5V and supports latching, but you will need to adjust the Arduino sketch to make it work with a different DAC. The DAC code is inside of the Laser.cpp file.

Step 5: Housing / Putting Everything Together

Picture of Housing / Putting Everything Together

If you don't have a box/case yet, now is a good time to get one. Don't forget to add an opening so that the laser ray can be emitted. I just used a wooden box and sawed a (too big) round hole and added a flap to open/close it. As you can see in the picture, I have plenty of room left, so I should have choosen a smaller box.

After everything is mounted, place the laser pointer near the galvos and adjust it so that it points into the center of the first galvo. I recommend to not fixate it at this point, so that you can re-adjust it later on.

The Arduino should be powered via USB, so you need to connect it to your PC (or later on to a USB charger) to run the laser show. You could also get the power from the galvo power supply, but this would require a DC-DC step down module, which is easy to add but out of scope of this project.

Your setup should look similiar to the one given in the image above, except for the extra (optional) amplifier PCB on the image, which will be explained later on.

Step 6: Software: Uploading the Laser Show to the Arduino

Picture of Software: Uploading the Laser Show to the Arduino

If you haven't already installed the Arduino IDE, now is a good time to do so.

You can download the complete laser show sketch from:

  • Download the project (Just click on the "Clone or Download" button and choose "Download ZIP").
  • Open the LaserShow/LaserShow.ino sketch in the Arduino IDE.
  • Connect the Arduino via USB.
  • Press the compile and upload button.

If you wired everything as explained, the Arduino should now run the laser show right away.

Since the laser pointer does not have a lot of power, you will need a dark place to fully enjoy the show. Of course you can upgrade the project to a more powerful laser diode, but this is not covered in this tutorial and requires additional safety measures.

Trouble shooting:

  • is the laser pointer not switching on/off? Check if it is wired correctly.
  • is the laser pointer hitting the galvos in the right position? Try readjusting the height/angle of the pointer.
  • are't the galvos moving? Check if the power supply is working. Check if the galvos move when you connect +5V and afterwards GND to the positive input of the driver card instead of the output from the DAC.
  • is the image flipped horizontally or vertically? (adapt the Laser.h header file to flip the projection)
  • is the image rotated 90 degrees (adapt the Laser.h file to swap X/Y)

Fine Tuning:
Have a look at the Laser.h file to fine tune various timings to your hardware. Your laser pointer might have a smaller/bigger on/off delay than mine and the galvos might react differently.

The galvo driver cards typically also have potentiometers to fine tune over/under shooting, so you might play with those as well. In my setup I still had problems reaching the closing point of a contour exactly, probably because of the overshooting.

Step 7: Bipolar Signal With Opamps

Picture of Bipolar Signal With Opamps

NOTE: you only need to do this step if you want to get a bigger projection angle or if you are eager to learn how to generate bipolar signals and their inverse.

In the previous steps, we have already built a working laser projector, but we did not generate the correct bipolar ILDA signal that the driver cards expect. So how does a bipolar signal work? Bipolar means that the signal swings from -5V to +5V (so it has a range of 10V and GND is the center). In additional, the ILDA standard wants the same signal again as an inverted signal. For example a negative ILDA input of e.g. -5V requires a positive ILDA input of +5V.

Want we want to build now is an amplifier circuit which amplifies the unipolar DAC signal (from 0V to +4.095V) to the bipolar range -5V to +5V. For this we need a bipolar power supply. Luckily we can just use the power supply of the galvos, which is bipolar.

We are going to build the amplifier for X and Y separately, since it is the exact same circuit. To amplify an analog signal and to invert it, an opamp (operational amplifier) is used. Since we want to make the amplifier adjustable, we will add potentiometers for the gain and the offset, instead of fixed resistors. This makes the whole setup adjustable to different input ranges from the DAC and different power supply voltages.

Parts needed:

  • 2x TL082 opamp (PDIP-8)
  • 2x 1 KOhm resistor
  • 2x 47 KOhm resistor
  • 4x 10 KOhm resistor
  • 4x 10 KOhm potentiometers

The above images show the circuit for one signal line, you need to build it two times. I generated a circuit view and a breadboard view. I decided to put it on prototyping PCB together with the DAC, but that is totally up to you, breadboards will work fine as well. My PCB is shown on the last image.

Finally you need to connect the two DAC outputs to the two amplifiers and their +/- output to the ILDA driver inputs. Make sure that you also connect the GND of the Arduino with the GND of the galvo power supply, to get a common ground. Connect the power supply to the two amplifiers as well. Now everthing should be setup and you can run the laser show and adjust the image using the potentiometers.

How the amplifier works

One potentiometer is used for the GAIN (it scales the image) and the other for the OFFSET (it moves the image). The TL082 IC contains two separate opamps. One opamp is used to move and scale the signal (and also invert it), the output is the negative ILDA INPUT-. The second opamp is used to invert the signal again to get the positive ILDA INPUT+.

Step 8: Further Project Extensions

You can extend this project in various way. If anyone is interested, I plan to write additional instructables that extend this project:

  • Upgrade to a Teensy 3.2 microcontroller and create a live spectrum analyzer


    (Source code here:

  • Add an ESP8266 to show content from the Web

  • Create an Etch-A-Sketch Webpage which sends the drawn sketch to the laser projector


badgift (author)2017-11-19

Hi Deltaflo,

Do you have any idea for connection SD card module in parallel with MCP4822?

DeltaFlo (author)badgift2017-11-19

You can use the CS (chip select) of the MCP 4822 to enable/disable if it listens to the serial data. A SD card also has a CS, so you can use that as well, the SD card library allows you to specify the CS.
So connect a spare digital pin to the mcp CS and set it to low when you want the mcp to listen and to high when you want to read from the sd.

bskywalker4 (author)2017-10-18

Thanks for putting this together - it's awesome. I just got this working and am trying to figure out how to do a simple raster pattern where it draws a horizontal line, then shifts down 1mm and draws another line, and repeats. How do i change the code to do this? I will also probably move this to a pcb, has anyone uploaded eagle or altium files yet?

Madjonnyboy (author)bskywalker42017-11-18

If you use glow in the dark paint (contains Zinc Sulphide) on the surface you want to project onto then you will get enough persistance to form an image. I have been thinking of using a rotating mirror on an old VCR head to produce the vertical component of a raster (it would be easy to sync to a video), a much faster motor will be required for the line frequency though. Good luck with generating some raster images. The code to draw a raster will be fairly simple, increment x until it reaches max, then make x = 0 and increment y, when y = max reset all to zero, increment your counter, repeat. Modulating your image from a file while where [ x,y]counter = laser on or off. I hope this was helpfull.

sqwee (author)2017-10-16

What power laser pointer did you use and how visible do you think it would be in a well lit room?

DeltaFlo (author)sqwee2017-10-17

I don't actually know the power of my laser pointer, since it was a merchandising gift. With a standard laser pointer, the room needs to be dark. If you use a more powerful laser pointer, it gets dangerous because you may not look into the laser anymore and you need protective glasses/gear.

AndreaB287 made it! (author)2017-10-12

Hi! I've just "repaired" my own dmx laser using an Arduino Mega. I'll try to interface it with dmx world to drive it by FreeStyler Software. Great Job !!! Thanks.

mogrinz (author)2017-10-06

Got mine working. I bought my Galvos here:

but there was *zero* information on what input voltage the galvos' power supply needed. The wire colors (yellow, blue, brown) were of no help. Eventually, I decided to just wire it up to a 120v/AC outlet and cross my fingers (assuming ground in the middle).

The power supply and galvo LEDs came on... success! Here is a pic which I hope will spare others hours of fruitless searching for the info. If your LEDs don't come on, swap the neutral and hot wires (maybe your power cord has them backwards. Ground is definitely in the middle)

RasecVicz (author)2017-09-24

Dear, on your fritzing opamp project, the "Gain Potentiometer" has a free terminal. I´m wondering if it is really this way, of if we need tie this leg on +15v or -15v power supply.

Can you answer me? Thanks

DeltaFlo (author)RasecVicz2017-09-24

That‘s correct, only two legs are connected.

badgift (author)2017-05-30

Is it possible to update your project on DAC714 chip?)

DeltaFlo (author)badgift2017-05-30

You would need two DAC714 and use the "Cascaded Serial Bus Connection with Synchronous Update" to synchronize. I think that this DAC is too good for the galvos, you will not really see the 16 bit resolution compared to the 12 bit resolution. The advantage of the DAC714 is that it is already bipolar, so you could use it to generate a bi-polar output. The problem here is that the reference voltages that you need for the DAC714 are not directly available from the power source (since it only has -15 / + 15 V), so you would still need some voltage dividers to get the correct bipolar reference voltages.

So I think you should just buy an MCP4822, it only costs 3-5 Euros.

badgift (author)DeltaFlo2017-06-09

Hmm I'm found the DAC8734EVM evaluate pcb, maybe it's help with 16bit conversion without any additional handmade?)

DeltaFlo (author)badgift2017-06-09

Yes, that would work, but the chip is overpowered, since it has 4 channels and you only need 2. The evaluation board costs around 50$ and as I said, I don't think that 16bit will provide much over the 12bit, since the Galvos are not that precise.

badgift (author)DeltaFlo2017-06-09

Precision of galvos is depend from galvo driver or galvo itself? Suppose if I will use 45kpps galvo system (no Scanlab of course, but not cheap).

DeltaFlo (author)badgift2017-06-09

I guess it is mainly the driver/feedback loop that tries to avoid over/undershooting. If you draw a rectangle, it is really hard to get the laser to point to the starting point exactly without drawing enough intermediate points and waiting at the edges. But if you use a better scanner/driver, the 16bit might make sense, if you want to invest the 50$.

badgift (author)DeltaFlo2017-05-30

Thanks for reply!

solaria137 made it! (author)2017-05-18

Got it working on an ESP8266, and converted some ILDA files (using LaserBoy and perl scripts) to use as objects and animations.

Generated a pretty good rendering of the ILDA12K test pattern. For example: the circle in the middle fits inside the square (almost) touching on each side. Only problem is it’s running at 20 KPPS rather than 12 KPPS. I’d like to adjust the tuning on the drivers, but there are 7 unlabeled potentiometers on each board, and I’d probably just make it worse.

Took a few changes to the program to get it to come out right:

Scan speed: At maximum, the ESP8266 can generate 30 – 40 KPPS… much more than the galvanometers can handle. Added throttling to sendToDAC() to allow the speed to be adjusted to a more reasonable 10 – 20 KPPS.

LASER_TOGGLE_DELAY: Removed the wait(LASER_TOGGLE_DELAY). Well, there’s still a ‘delay’, but it doesn’t use a ‘wait’. The comment in the Laser.h file is misleading:

// Defines how long the galvos wait for the on/off toggling of the laser pointer (in microseconds), this will depend on your laser pointer.

It’s not the laser pointer that’s the problem, it’s the galvos: it takes a couple hundred usecs for the mirrors to settle down after a move command. If you stop sending data and wait() until the mirrors come to a rest before toggling the laser, it slows down the scan rate and messes up the test, which expects a continuous data stream. The circle in the middle of the test pattern becomes a spiral... My solution is to put the toggle commands into a queue and process them later so that the mirrors are constantly moving:


int ttlNow = 0;
int ttlThen = 0;
int ttlQueue[16];

int SCANNER_KPPS = 20;
int LASER_QUALITY = 4096;


void Laser::on()
if (!_state && !_laserForceOff) { _state = 1; ttlQueue[ttlNow] = 1; }

void Laser::off()
if (_state) { _state = 0; ttlQueue[ttlNow] = 0; }

void Laser::scanner_throttle() {
while (_last_scan + (1000/SCANNER_KPPS) > micros());
_last_scan = micros();

ttlThen = (ttlNow - (LASER_TOGGLE_DELAY * SCANNER_KPPS / 1000) + 16) & 0xf;
if (ttlQueue[ttlThen] >= 0) {
digitalWrite(_laserPin, ttlQueue[ttlThen]);
ttlNow = ++ttlNow & 0xf;
ttlQueue[ttlNow] = -1;

void Laser::sendToDAC(int x, int y)
int x1 = y;
int y1 = x;
int x1 = x;
int y1 = y;
x1 = 4095 - x1;
y1 = 4095 - y1;


x1 &= 0xfff;
digitalWrite (SS_PIN, LOW);
SPI.transfer((x1 >> 8) | commandBits1);
SPI.transfer((x1 & 0xff));
digitalWrite (SS_PIN, HIGH);

y1 &= 0xfff;
digitalWrite (SS_PIN, LOW);
SPI.transfer((y1 >> 8) | commandBits2);
SPI.transfer((y1 & 0xff));
digitalWrite (SS_PIN, HIGH);

// latch
digitalWrite (LDAC_PIN, LOW);
digitalWrite (LDAC_PIN, HIGH);


solaria137 (author)solaria1372017-05-20

Here are the animations.

DeltaFlo (author)solaria1372017-05-20

That looks nice... Are you using your own methods for writing to the DAC?

If I find some time I will incorporate the laser throttling into my source... You are right that it takes a lot of scan time if one waits for the toggling at the given position, so your solution is better, especially for patterns with many on/off states. Regarding the screws/potentiometers, I found documentation for mine, but I also had trouble adjusting them adequately.

solaria137 (author)DeltaFlo2017-05-21

Yes, when I first put it together, I had 2 * single DACs and an ESP8266, so DAC_MCP4X() had to be changed. Since the DACs only require a couple of statements, it was easier to just put them into sendToDAC().

Right now the resolution of the toggle queue is (1000/SCANNER_KPPS) usecs, so it doesn't work very well for slow scan speeds, < 10 KPPS. (Adding a fine-tuning to the toggle delay...)

The toggle queue solves the ILDA patterns, but it doesn't add much to the original LaserShow graphics, especially text. For that, waiting for the mirrors to come to a stop before each line segment seems to produce better results.

DeltaFlo (author)solaria1372017-05-21

Yes, that confirms my results... to get a sharp line ending/edge, one needs to wait for the mirror to fully stop, otherwise one gets an round edge or undesired trail at the end of a line.

solaria137 (author)DeltaFlo2017-05-24

The difference is that the ILDA objects have those optimizations built into the object, rather than the scanner driver. Causes problems when you display an ILDA object on Lasershow (for example the ILDA12K test object), it essentially gets optimized twice. Same thing in the other direction: displaying a LaserShow object on a driver without full stops, doesn't get optimized at all.

I ran the Logo object through the LaserBoy optimize, and added an optimized font. Here's the result at 20 KPPS, 120 usec TTL delay, using the toggle queue, no stops. Image refreshes about 20 times/second, so some flicker, but not too bad.

huangxiaomin made it! (author)2017-05-22

hello,Deltaflo.Can you help me?I used proteus to do a simulation, when I enter 0V is that it should output -5V, the actual result is 5V, is there any problem with me?

DeltaFlo (author)huangxiaomin2017-05-23

That is correct. When you enter 0 you get -5V and +5V and when you enter 5V you get +5V and -5V. That is the idea of a bipolar signal that is transmitted redundantly.

LevTronic made it! (author)2017-02-03

Many thanks for the great project. It is exactly what I was looking for. I plan to project a simple time and the date when needed to the wall. For that I have a rtc3231 with on the board provided. I have unfortunately a small problem. Why is everything twisted in x-direction? I have the opamps synonymous built according to your circuit. Pin 1 of the respective opAmp goes to ilda- and Pin 7 to Ilda + or do I have to invert one of them?

mariusdabija (author)LevTronic2017-04-24


I have seen your comments and the fact that you have had good results with this project. It impressed me how you made the PCB component. Unfortunately the picture with the electronic circuit is at a low resolution and I do not realize the value of all the components. Please help me and attach the PCB diagram (in PDF format) because I would like to realize this project too.

Thank you in advance!

LevTronic (author)mariusdabija2017-04-25

(I thought I had already answered but I do not see my answer here)

mariusdabija (author)LevTronic2017-05-03

I could not tell you what was connecting the two pins. Unfortunately, I do not see the photo on the Arduino plate. Can you help me?

LevTronic (author)mariusdabija2017-05-04

These pins are for the connection of a real-time clock. These are the pen plus, minus, scl and sda. I have the module RTC DS3231 on the pcb-board integrated.

mariusdabija (author)LevTronic2017-05-04

Ok. Thank you very much!

mariusdabija (author)LevTronic2017-05-03

I'm trying to contribute a few things ... I hope I did not make a mistake.

LevTronic (author)mariusdabija2017-04-25

Hi, I have created the layout with sprint layout. I can send you the data. Maybe you can use the attached JPG file. greetings

mariusdabija (author)LevTronic2017-04-26

Thank you!

It helps me very much. I will make time and I will make this project. Then I'll send you pictures of what I've done. I'm a novice :) but I hope to go right.

Thanks for the help!

DeltaFlo (author)LevTronic2017-02-03

You can also invert x in the code, there is a #define in Laser.h to flip in x and y direction.

Funny, I actually did the same, the projector shows date/time, weather report and per date infos onto my bed room wall. I added Wifi so that it can get weather and other infos from the web.

LevTronic (author)DeltaFlo2017-02-03

Many thanks, that was the solution. In future I will also be able to spend a few more info, which is to be asked about an esp-12e module but unfortunately I still lack the necessary knowledge around the programming of the arduino. What do you think the use of a stm32 would reduce the flicker?

LevTronic (author)LevTronic2017-02-03

... Or are the galvos too slow?

DeltaFlo (author)LevTronic2017-02-03

A faster micro controller helps a bit, I am using a Teensy 3.3 (or nowadays a 3.5). The nice thing is that it is almost 100% compatible with the arduino. But don't expect it to get much smoother (maybe a factor of two faster), the final limit are the galvos. When they are driven too fast, the lines get non-linear. You can try that with the Arduino already, if you change the quality parameter in Laser.h it will send less intermediate points and you can see the non-linear movement.

A Teensy works very nice to communicate with the esp over serial because it has two hardware serial lines.

LevTronic (author)DeltaFlo2017-03-03

Hi, I now have a teensy 3.5 but only the laser flickers. I have made the connections 1:1. There is no movement of the galvos. Where do I have to make changes to the sketch for the teensy? Can you please help me?


DeltaFlo (author)LevTronic2017-03-03

Did you connect the correct SPI CLK and MOSI pins to the MCP4822?

LevTronic (author)DeltaFlo2017-03-03

Thank you for your fast feedback.

Same Pin Numbers as Nano or Pro Mini

Teensy: 10 - CS0, 11 - MOSI0 , 13 - SCK0

DeltaFlo (author)LevTronic2017-03-03

Try disabling MCP4X_PORT_WRITE on the MCP library header file, maybe the port writing does not work on Tennsy 3.5?

On my Teensy 3.2 it worked out of the box, the only thing I had to change was the gain in the MCP library because the voltage is only 3.3V, but even witout changing the gain, you should see an image... If the galvos don't move it has to be the wiring of the MCP.

huangxiaomin (author)DeltaFlo2017-04-20

呃,can i use uno to enjoy it?

LevTronic (author)DeltaFlo2017-03-03

thank you but unfortunately did not help :-(

When compiling I noticed however:

Laser.cpp:155: warning: 'y' may be used uninitialized in this function

outcode1 = computeOutCode(x1, y1);

Laser.cpp:153: warning: 'x' may be used uninitialized in this function

x1 = x;

myLaserShow: In function 'void drawArduino2DRotate()':

myLaserShow:208: warning: unused variable 'hX'

long centerX, centerY, hX, hY, w,h;

myLaserShow:208: warning: unused variable 'hY'

long centerX, centerY, hX, hY, w,h;

myLaserShow: In function 'void drawScroller(String, float, int, int)':

myLaserShow:341: warning: comparison between signed and unsigned integer expressions

for (int c = 0; c < s.length() + maxChar; c++) {

myLaserShow:367: warning: comparison between signed and unsigned integer expressions

if (c<s.length()) {

Opening Teensy Loader...

DeltaFlo (author)LevTronic2017-03-03

No, I don't think it is those warnings...

Hm, try a minimum example with the MCP library and write 0 and 4095

using dac.output2(value1, value2) and check if you get 0 and 3.3V on the outputs of the DAC.

LevTronic (author)DeltaFlo2017-03-03

I'm not quite sure but I think you mean at this position?

// Called by the output* set of functions.

void MCP4X::output2(unsigned short data_A, unsigned short data_B) {

data_A=0; data_B=4095; <------------ i have put This

this->output(MCP4X_CHAN_A, data_A);

this->output(MCP4X_CHAN_B, data_B);

I Have only 0V and 2V on the Output Pin6 and Pin8 on DAC

Can a level shifter help here?

LevTronic (author)LevTronic2017-03-03

Uups, with an Arduini ProMini i have the same Results :-O

0V and 2V

LevTronic (author)LevTronic2017-03-03

I have made 2 pictures with my mini osziloskop. These are the start sequences after the turn on. Can do with the fact that the Teensy with 120MHz. Is clocked?

Picture1 ProMin

Picture2 Teensy 3.5

DeltaFlo (author)LevTronic2017-03-04

Probably the Teensy is so fast that the galvos don't move at all.

2V is fine, because the MCP only gets 3.3 V and if gain is set to 1X, you get 0 - 2.047V instead of 0 - 4.096 with gain 2X and 5V. Gain 2X does not work with 3.3V because the MCP can not go above 3.3V, so the output will be clamped.

Regarding the speed, yes, you need to adjust the Laser.h parameters:

improve the quality:


enable the move delay:


Try putting laser quality between 1 - 16 and laser move delays between 1 - 10.

DeltaFlo (author)DeltaFlo2017-03-04

Another thing, the MCP library uses the old deprecated SPI API to set clock speed, see

for details. This means the SPI speed depends on the MHz of your Teensy. Try compiling with 96Mhz (which is what I used with my Tennsy) instead of full speed. Alternatively the SPI init code in the MCP library could be changed to use SPISettings and SPI.beginTransaction() to specify a fixed SPI clock rate across all micro controllers.

About This Instructable




Bio: I'm a software guy, starting to learn electronics.
More by DeltaFlo:DiscoJar: Sound Reactive Lamp With 288 RGB LEDsArduino Laser Show with real galvos
Add instructable to: