DoESLiverpool / somebody-should

A place to document practices on the wiki and collect issues/suggestions/to-do items for the physical space at DoES Liverpool
32 stars 11 forks source link

Finish and box the laser galvo setup #879

Open goatchurchprime opened 6 years ago

goatchurchprime commented 6 years ago

Convert oscilloscope game to use big lasers

Sean has the galvos with mirrors bought for about £40. We were successfully testing it by drawing rotating squares using the technology of 2 DACs on an Arduino Due (see code below).

He now has the parts (including amps) for amplifying the 2V of the Due to the 10V of the galvos: https://create.arduino.cc/projecthub/ArduPic/how-to-modify-analog-output-range-of-arduino-due-6edfb5 He also has a latching laser, so it can be blanked out when moving from one polygon edge to the next.

The galvos have some inertia and follows predictable curves. We need to apply a steady velocity to one axis, and a square wave to the second axis. If we photograph and analyze the curves, they might be able to replicate them in a simulation, which we can use to develop the voltages to apply to make the device adhere to interesting curves. (It's an effectively dampled system; the point does not oscillate or overshoot the target, no matter from how far away it starts.)

Eventually, we'll have a device that can operate from a serial interface to receive a frame comprised of about 100 line/curve segments (about 4 bytes each, for 12 bits per channel, counter number of subdivisions, and one bit for the shutter) in about 0.5Kb, so that this frame will be repeated until a new frame supplied by a second controller replaces it.

void square(int cx, int cy, int rx, int ry, int segs)
{
    analogWrite(DAC0, cx - rx); 
    analogWrite(DAC1, cy - ry); 

    for (int i = 1; i <= segs; i++)
        analogWrite(DAC0, cx - rx + 2*i*rx/segs);
    for (int i = 1; i <= segs; i++)
        analogWrite(DAC1, cy - ry + 2*i*ry/segs);
    for (int i = segs-1; i >= 0; i--)
        analogWrite(DAC0, cx - rx + 2*i*rx/segs);
    for (int i = segs-1; i >= 0; i--)
        analogWrite(DAC1, cy - ry + 2*i*ry/segs);
}

void setup()
{
    analogWriteResolution(12);
    Serial.begin(9600); 
}

float th = 0; 
void loop()
{
    int r = 413; 
    th = th + 0.02; 
    float bth = th; 
    float sfac = 1500; 
    square(2000+sfac*cos(bth), 2000+sfac*sin(bth), -r, -r, 800); 
    bth += 3.1415926/2; 
    square(2000+sfac*cos(bth), 2000+sfac*sin(bth), r, -r, 800); 
    bth += 3.1415926/2; 
    square(2000+sfac*cos(bth), 2000+sfac*sin(bth), r, r, 800); 
    bth += 3.1415926/2; 
    square(2000+sfac*cos(bth), 2000+sfac*sin(bth), -r, r, 800); 
}
amcewen commented 6 years ago

Here's a video of what it looks like so far

ajlennon commented 6 years ago

So how do we convert star wars to vector format?

Presumably the starting point is some kind of edge detection?

Then what ?

amcewen commented 6 years ago

Now with blanking (see the progress Instagram video)...

const int kBlankingPin = 13;

void square(int cx, int cy, int rx, int ry, int segs)
{
    analogWrite(DAC0, cx - rx); 
    analogWrite(DAC1, cy - ry); 

    delayMicroseconds(1200);
    digitalWrite(kBlankingPin, HIGH);
    for (int i = 1; i <= segs; i++)
        analogWrite(DAC0, cx - rx + 2*i*rx/segs);
    for (int i = 1; i <= segs; i++)
        analogWrite(DAC1, cy - ry + 2*i*ry/segs);
    for (int i = segs-1; i >= 0; i--)
        analogWrite(DAC0, cx - rx + 2*i*rx/segs);
    for (int i = segs-1; i >= 0; i--)
        analogWrite(DAC1, cy - ry + 2*i*ry/segs);
    delayMicroseconds(300);
    digitalWrite(kBlankingPin, LOW);
}

void setup()
{
    analogWriteResolution(12);
    Serial.begin(9600); 
    pinMode(kBlankingPin, OUTPUT);
    digitalWrite(kBlankingPin, HIGH);    
}

float th = 0; 
void loop()
{
    int r = 413; 
    th = th + 0.02; 
    float bth = th; 
    float sfac = 1500; 
    square(2000+sfac*cos(bth), 2000+sfac*sin(bth), -r, -r, 800); 
    bth += 3.1415926/2; 
    square(2000+sfac*cos(bth), 2000+sfac*sin(bth), r, -r, 800); 
    bth += 3.1415926/2; 
    square(2000+sfac*cos(bth), 2000+sfac*sin(bth), r, r, 800); 
    bth += 3.1415926/2; 
    square(2000+sfac*cos(bth), 2000+sfac*sin(bth), -r, r, 800); 
}
Sean-anotherone commented 6 years ago

Had plans for makernight this week - to throw together a small differential amplifier to better couple the 0.5 - 2.75 V output from the DACs on the arduino due to the 10V input on the galvo set.... that kinda got lost.

Instead, the galvo set is now mounted on a nice screw-adjustable 5mm thick aluminium plate together with a ttl modulated laser that's nicely aligned,,plus, with a bit of tinkering and some help from Adrian who is rather more familliar with the due IDE than I, the ttl blanking is both worked out and proven on a modded version of the initial test code.

Currently, the laser is just blanked for "about the right amount of time" between squares - implementign this properly will need more thought as differing shapes and sizes will need differing blanking times, so a bit of a rethink in how the primitives are drawn might be needed. But not only is the hardware mounted up, it all works including the blanking, so a productive couple of hours methinks !

tb942 commented 6 years ago

The comment on the lasers being blanked for 'just the right amount of time' is an interesting one - it's only true to an extent...

That delay doesn't just delay the blanking, but also the positioning of the squares - I wasn't really paying attention for that bit of development, but from looking at the code, without the blanking it theoretically works perfectly - the need for the delay is as Julian mentioned at the top of the thread, the damped nature of the galvo. So the microcontroller will think the dot is at one point, when in reality it's still only halfway there from the last point - hence slightly rounded corners on your squares.

A simple solution would be to stop using analogue write, and instead use a function that you write yourself that encompasses the write and the delay.

Something along the lines of:

#define timeConst 1234                        //Will need figuring out
int oldX = 0, oldY = 0;                       //declare and define storage variables (unsure if global is needed)

void writePosition (int x, int y){
    analogWrite(DAC0, x);                    //write x position
    analogWrite(DAC1, y);                    //write y position
    if (abs(oldX - x) > abs(oldY - y))       //if x change is bigger than y change.....
        delayMicroseconds(abs(oldX - x)*timeConst);  //wait x change * time constant
    else                                             //if y change is bigger than x change.....
        delayMicroseconds(abs(oldY - y)*timeConst);  //wait y change * time constant
    oldX = x;                                        //update x storage variable
    oldY = y;                                        //update y storage variable
}

-pls note this ^ will probably have errors, I've just done it on my phone, so no error checking

Edit(s) - made it readable and more likely to work... Edit 54,632 - I can verify that this will compile for the Due now...

Sean-anotherone commented 6 years ago

I was just happy to get the ttl blanking to work ! :)

goatchurchprime commented 6 years ago

I think the right answer is to use an SPI-controlled DAC that delivers the two-channel bipolar -10V to 10V we need to drive the galvos, because then we don't need any amplifiers.

Options are:

MAX532 for £12 (through-hole) which has been tried on a Teensy

DAC8734 with an evaluation board for £42 and a writeup of driving one from an Arduino

MAX5661 which doesn't have any prices, but has a writeup and is 16 bits of precision.

MX7837 for about £16 and has through hole version, but not much information.

So, the MAX532 could be the best option, though it seems to need an external Op-Amp to run bipolar (please check if we can do). If we think it's the right thing, I'll order two ASAP so we can start building.

In theory we can run this with 5 wires coming out of the device for {GND, Power, CLK, DIN, LaserLatch} where the Power is about 5V and comes out of the laser device, so it can power a microcontroller (though if the microcontroller is plugged into a laptop then this wiire won't be connected).

We'll be able to try this with interchangeable microcontroller devices for development. Eventually it would be controlled remotely through wifi receiving high level commands to write words, to begin with.

amcewen commented 6 years ago

The MAX532 seems like it'd do the trick. Why do you need to order two? Is that for a spare? It's got two voltage outputs on the chip, so one chip would drive both axes.

Shame it doesn't recommend any particular op-amp for the bipolar output. I've got a few op-amps lying round, if you want some (you'd need two op-amps, AFAICT) and they're good enough (I'm not sure what you'd need to be worrying about with an op-amp for that). Dunno if you've any thoughts on that @tb942?

tb942 commented 6 years ago

The op amp to run the max532 would be no problem, but at the point that were doing that, why not just put the op amp on the due's DAC outputs and accept that? - 12 bit each way is plenty - a lot more than 4k resolution...

I just don't see massive advantage in an external DAC when we'll have to set up an op amp to enable full range bipolar operation anyway

Sean-anotherone commented 6 years ago

The separate DAC was a seed that I sowed after reading the notes on the Ocelot console - the DACs onboard arduino/pic are OK but a dedicated device performed much better.

Given that the opportunity to scale the output would be desirable, I reckon the MAX532 then an op amp stage with gain ~0.1 - 1 driving the galvo board.  This would allow the ability to scale back at the analog stage if a narrower "throw angle" is required, but keeping the full 1:4096 resolution.

  From: tb942 <notifications@github.com>

To: DoESLiverpool/somebody-should somebody-should@noreply.github.com Cc: Sean Jarman sean.jarman@yahoo.co.uk; Assign assign@noreply.github.com Sent: Wednesday, 19 September 2018, 21:25 Subject: Re: [DoESLiverpool/somebody-should] Finish and box the laser galvo setup (#879)

The op amp to run the max532 would be no problem, but at the point that were doing that, why not just put the op amp on the due's DAC outputs and accept that? - 12 bit each way is plenty - a lot more than 4k resolution...I just don't see massive advantage in an external DAC when we'll have to set up an op amp to enable full range bipolar operation anyway— You are receiving this because you were assigned. Reply to this email directly, view it on GitHub, or mute the thread.

tb942 commented 6 years ago

Ah, fair enough, in that case then yeah,

If you wanted to get a truly variable throw angle, you could use a good quality dual (to get both channels on one knob) 20k potentiometer in the op amp circuit in place of the 20k resistor in figure 10 in the max532 datasheet. (Maybe use a logarithmic pot so it's most accurate in the 0.1-1 range)

tb942 commented 6 years ago

www.ti.com/lit/ug/slau525/slau525.pdf This may be useful

tb942 commented 6 years ago

As for op-amp of choice, a tl072 would do you pretty well - a pretty flexible general amp which takes up to 36v supply, so would handle +-10v fine, plus I have a bunch of them that I'd be happy to bring you - I'm hoping to make maker night tonight, however may not be able to hang around too long, but I'll aim to at least leave you some to play with.

goatchurchprime commented 6 years ago

The advantage of running this as an SPI device is that we can choose different microcontrollers -- or even run this from a RaspberryPI. Also, isn't the overall circuit (including the op-amp to make it bipolar) much less than the circuits required to make a bipolar instrumental amplifier?

goatchurchprime commented 6 years ago

I've ordered one "MAX532BEPE+ DAC, 12BIT, DUAL, DIP-16" from Farnell. Feel free to open the packet, and put the two extra reed switches on my desk

jrp commented 6 years ago

Having had a read of the datasheet (which is as clear as mud) it appears that this solves the amplifier problem as well as the dac problem. it even seems ot have a programable amplifer, so it shoudl be possible to do what would have been doen with pots in software. I take it my mucking around with op-amps isn't required?

goatchurchprime commented 6 years ago

the chip from farnell is in a cardboard box in the galvo parts bin in the cupboard. Set it up by the time I get home next week

On Mon, 24 Sep 2018, 17:47 jrp, notifications@github.com wrote:

Having had a read of the datasheet (which is as clear as mud) it appears that this solves the amplifier problem as well as the dac problem. it even seems ot have a programable amplifer, so it shoudl be possible to do what would have been doen with pots in software. I take it my mucking around with op-amps isn't required?

— You are receiving this because you were assigned. Reply to this email directly, view it on GitHub https://github.com/DoESLiverpool/somebody-should/issues/879#issuecomment-424044430, or mute the thread https://github.com/notifications/unsubscribe-auth/AApVhrjAmx2E5v1qfLbxgvZRyi2d59NJks5ueQySgaJpZM4V4UVz .

Sean-anotherone commented 6 years ago

The data sheet is not the most helpful, but connecting the SPI interface and power supply will only take 5 mins on a breadboard so I spent this thursday making a case for it all to go inside instead - this needs an exit aperture and some holes for mains lead etc. cutting but won't take long to finish and glue together.

Teh programmable gain amplifier is one of the modes in which the device can be used - instead of a regular DAC the DAC ladder is used as the gain resistor for the op amp - giving a 4096 bit gain control. We're using it in dual DAC mode so an external op amp will probably still be required, but need to tickle the device with some code and connect it to the galvos first to see what we get, probably get to this next Thurs.

DocTrucker commented 6 years ago

Some interesting conversations on this hack a day post relating to dac control of galvos and laser optics:

https://hackaday.com/2018/02/15/laser-galvo-control-via-microcontrollers-dac/

goatchurchprime commented 6 years ago

I've got 2 more of these MAX532s in the box of parts, just arrived from Farnell, so hopefully we can get this done without blowing up our whole supply.

goatchurchprime commented 6 years ago

Spent the evening with proper circuit and had no response from the device at all. Checked all the connections and data bits using a scope.

Only next option is to try the code and wiring giving here from a Teensy in case there is a misunderstanding of the SPI protocol https://forum.pjrc.com/archive/index.php/t-50057.html

ajlennon commented 6 years ago

You had a go with that cheap USB logic analyser of mine that @amcewen got working?

It'll auto-decode SPI I believe?

goatchurchprime commented 5 years ago

We've given up on the MAX532s after last night on makernight. We were using a teensy, which was getting about 10% of the data through, with a lot of noise (digital noise; it wasn't picking up the position).

@Sean-anotherone I've moved the components into a labelled drawer (with our names on it) to the left of the solder station, in case you're looking. We can package and label up the MAX532s and put them into one of the component drawers as an expensive dead end, before getting on with one of @magman2112's hopefully superior DACs, which we will try.

goatchurchprime commented 5 years ago

We have 2 mcp4822 DACs in the laser galvo drawer, for being experimented and wired up

amcewen commented 5 years ago

Once you've got asteroids working on it and want some stretch goals :-D

Actually there's a load of documentation about his software (and some on the hardware) for doing bitmap displays(!!) on an oscilloscope in that link