Electromagnetic Graphics Tablet V2

by lingib in Circuits > Arduino

181 Views, 2 Favorites, 0 Comments

Electromagnetic Graphics Tablet V2

puck_exploded.jpg
puck_assembled.jpg
completed1.jpg
raw data.png
table_from_ raw curves.png
Electromagnetic Graphics Tablet V2
Measuring Distance & Position

This instructable explains how to make a simple electromagnetic graphics tablet that tracks the position of a handheld “puck” and displays its position on screen.


This project is a proof of concept, but it produces consistent and repeatable results even with manual construction. [1]


The accuracy, while not perfect, is excellent.


The system uses:

  1. Two wire grids arranged at right angles
  2. A small puck that generates a signal
  3. An Arduino UNO to read and process the signals


As the puck moves, the Arduino calculates its position based on how the signal is picked up by the wire grids.


Construction is simple ... all you require is:

  1. a sharp knife,
  2. a pair of side-cutters,
  3. a small screwdriver,
  4. a soldering iron,
  5. and access to a 3D printer.


All construction details, including code and STL files for 3D printing, are provided. [2]


Images

  1. Fig.1 (cover photo) shows an exploded view of the tablet cursor (“puck”).
  2. Fig.2 shows the assembled puck.
  3. Fig.3 shows the completed tablet
  4. Fig.3 shows the “raw” accuracy ... both diagonals should be straight
  5. Fig.4 shows the same plot after linearization


Videos

  1. Video 1 shows the tablet in operation.
  2. Video 2 shows how the load voltage varies as the puck moves across the wire grids.


Note

[1]

This design improves on an earlier version by using a signal emitted from the puck rather than a magnetic sensor.

  1. https://www.instructables.com/Electromagnetic-Graphics-Tablet/


This has the following advantages:

  1. The cursor aligns directly with the puck
  2. The puck can be rotated without affecting position
  3. Construction is simpler


Linearisation tables are used to improve the accuracy.


[2]

Instructions for sending the “output.nc” file produced by Processing to a plotter using my “XON_XOFF_TERMINAL” program may be found in my instructable https://www.instructables.com/Electromagnetic-Graphics-Tablet/ .

Supplies

The following parts were obtained from https://www.aliexpress.com/

  1. 1 only arduino UNO R3 with USB cable.
  2. 2 only arduino prototype boards for mounting the components.


The following parts were obtained locally

  1. 3 only LM358 op amps
  2. 4 only 100K ohm resistors
  3. 6 only 10K ohm resistors
  4. 8 only 1K ohm resistors
  5. 1 only IP67 dome push-button
  6. 1 only 2N7000 enhancement MOSFET
  7. 1 only 47nF capacitor
  8. 2 only 100nF capacitor
  9. 2 only 47uF 16 volt electrolytic capacitor
  10. 1 only spool 0.4mm diameter enamelled copper wire
  11. 4 only M3 x 10mm bolts
  12. 4 only M3 nuts
  13. 1 only 17 inch x 17 inch sheet of cardboard (see text)
  14. 1 only roll 12mm width doubled sided tape.
  15. 1 only roll 2 inch white cloth adhesive tape.
  16. 1 only 4-cell AA battery box
  17. 4 only AA 1.5 volt penlight batteries
  18. Hookup wire (various colours)



The following components are 3D printed

  1. 1 only coil former
  2. 1 only puck base
  3. 1 only puck cover


The STL files for these components are included further on.


The estimated cost, excluding postage, is less than $80.00

Theory

Induced currents 1.jpg
Induced currents.jpg
671cf84d-09e7-4512-93e5-9760650e3096.jpg
Displaced Grids.png

This may be a new method for determining distance and 2D positioning as I haven’t seen it published anywhere.


Induced Currents

Fig.1 shows a resistive load attached to a loop of wire. A circulating current is flowing in the orange coil. This current induces currents into the adjacent wires.


  1. In the lower diagram there is no voltage across the load as the induced currents cancel.


  1. In the top diagram the amplitude of the induced voltage across the load remains constant as the coil approaches the load. This wire arrangement doesn’t allow us to measure distance ... but what if we change the wire shape.



In fig.2 the wire loop now has a serpentine shape. A circulating current is flowing in the orange coil. This current induces currents into the adjacent wires.


  1. When the coil is positioned between two adjacent wires (top diagram) the induced currents add.


  1. When the coil is positioned over a wire (bottom diagram) the induced current oppose each other


  1. When the coil is moved towards the load the voltage across the load varies in a sinusoidal manner which means we can now measure distance !!!!



Distance Measurement

In fig.3 a second identical serpentine winding has been introduced.


  1. The second winding is displaced sideways such that when the voltage across the top load resistance is a peak, the voltage across the lower load resistance is zero.


  1. We now have sine and cosine waveforms which allows us to calculate the position of the puck within each four inch “pitch”. [1]
  2. Angle = atan2( SIN / COS)
  3. Position = Pitch * Angle / 360


  1. The total distance moved can be calculated by summing the angle-difference between successive samples:
  2. Accumulated-angle += angle-difference between successive samples [2]
  3. Distance = Pitch * accumulated-angle / 360


2D positioning

  1. Two sets of grid wires at right angles, as shown in fig.4, allow you to determine your XY 2D coordinate.


Note

[1]

  1. The “pitch” is 4 inches if the serpentine wires are spaced 2 inches apart.
  2. Other pitches may require a change of coil diameter.


[2]

  1. This formula assumes that you start from coordinate (0,0) and never lift the puck. If you raise the puck it won’t be able to induce currents into the grids and your accumulated angle will become invalid.

The Puck

puck_circuit.png
damped wave.png
contiuous wave.png

The puck (tablet cursor) comprises a cross-hair surrounded by a 50Khz (kilohertz) alternating magnetic field. This field is detected by serpentine wire grids within the tablet and converted into positional information.


Unlike my earlier tablet, in which the puck had to be maintained both flat and horizontal, this puck only has to be kept flat [1]


Rather than using an oscillator circuit to create the 50 Khz alternating magnetic field, I’m pulsing the coil in fig.1 once every cycle with a 1us pulse from Timer1 causing it to “ring”. This has a number of advantages:

  1. The frequency doesn’t drift
  2. The pulse from the Arduino allows synchronous detection.


In fig.2 the LC circuit, which is resonant at 50KHz, is being pulsed once every millisecond. Each pulse results in approximately 30 damped oscillations due to the LC circuit “ringing”.


In fig.3 the same LC circuit is being pulsed once every 20us (microseconds). The amplitude of the waveform across the coil is now constant as any losses are being replenished. [2]


Notes

[1]

  1. https://www.instructables.com/Electromagnetic-Graphics-Tablet/


[2]

  1. The peaks are 20uS apart which equals 50KHz.
  2. The pulses are generated by the Arduino.
  3. Each pulse has a peak amplitude of 6 volts/40 ohms=150mA which creates a strong magnetic field in the inductor. When the MOSFET turns off, the collapsing field charges the 47nF capacitor ... which then discharges through the coil creating a magnetic field ... which then collapses charging the capacitor, and so on. The resulting waveform is a damped oscillation at the resonant frequency of the LC circuit.
  4. The 3us pulse-widths shown in fig.2 allow the magnetic field in the puck to reach maximum field strength. In practice the circuit works if the pulse-width is reduced to 1us.

Puck Construction

puck_exploded.jpg
puck_wired.jpg
puck_assembled.jpg

Fig.1 shows an exploded view of the puck.


The puck comprises four parts ... a 3D coil-former, a 3D base, a 3D top, and a strip of prototype board to hold the electronic components.


Fig.2 shows the wiring and how the coil is attached to the puck base. The tinned copper wire cross-hairs are inserted into the holes provided in the base before attaching the coil assembly.


The coil comprises 50 turns of 0.4mm diameter enamelled copper wire around the coil-former. Start and end holes are provided.


Fig.3 shows the assembled puck.


STL Files

2_inch_dia_coil_former.jpg
puck_active.jpg
puck_active_top.jpg

Down load each of the attached STL files:


  1. 2_inch_dia_coil_former.stl
  2. puck_base.stl
  3. puck_top.stl


Each of the above files were printed on a Voxelab Aquila 3D printer using PLA filament, a 0.4mm diameter nozzle, and 0.2mm layer height.


The Graphics Tablet

Graphics Tablet.jpg

The graphics tablet comprise two sets of grid wires as described earlier. One set of wires generates sine and cosine waveforms for the horizontal axis ... the other set generates sine and cosine waveforms for the vertical axis.


Each grid is terminated in a 1K ohm load resistor.


The waveform that appears across each load is amplified 10 times by means of an inverting op-amp. The op amp outputs are connected to the Arduino ADC inputs via a 1K ohm current limiting resistor should something go wrong. [1]


To enable the output signal to swing positive and negative the non-inverting input of each op-amp is connected to Vref = 2.5 volts.


The puck, which is powered from a separate 6 volt supply, receives a 1us pulse every 20us from Arduino pin 9. Each pulse triggers the MOSFET causing the puck’s LC circuit to “ring” at 50 Khz. This 50KHz signal is picked up by the serpentine windings allowing the puck’s position to be calculated.


The puck’s push-button is connected to Arduino pin 8.


Notes

[1]

The gain-bandwidth of an LM358 op amp is between 1MHz and 1.5MHz.


The gain of each op amp has been set to 10 to keep within this limit:

  1. 10 x 50KHz = 500Khz


Tablet Construction

tablet1.jpg
tablet2.jpg
tablet3.jpg
tablet4.jpg

Fig.1

Decide on your working area. The tablet shown in fig.1 is 16 inches by 16 inches but feel free to make it larger or smaller. I’ve cut 1/2 inch deep slots slots at one inch intervals around the perimeter.


Tip:

Cut enough slots along each edge such that the ends of the sine and displaced cosine windings enter on the same side and exit at the same corner.


Fig.2

Wire has a habit of drifting sideways. To eliminate this I placed strips of double sided adhesive tape horizontally to hold the wire strands in place as shown in fig.2. Once the backing layer was removed I did the same vertically.


Fig.3

Fig.3 shows four 2-inch wide serpentine arrays. Two arrays are displaced 1 inch horizontally and two are displaced 1 inch vertically. This interleaving produces the sine and cosine waveforms described in the theory section. Each wire is pressed onto the doubled-side tape to prevent the wires from shifting when they are being covered.


Fig.4

Fig.4 shows the wire arrays covered with 2 inch wide white fabric adhesive tape. This tape prevents the wires from moving and protects the surface on which the tablet is placed. The uncovered return wires will be covered with tape in the next step.

ADC (Analog-to -Digital-Conversion)

contiuous wave.png

Fig.1

  1. The blue pulses in fig.1 trigger the MOSFET in the puck.

The yellow trace is the ringing waveform induced in a serpentine grid by the puck.


Sampling

  1. The peak amplitude of the yellow waveform 10 us (microseconds) after the trailing edge of the blue pulse is the same in each cycle.
  2. If we were to sample the first peak using Arduino pin A0, and the second peak with Arduino pin A1, the ADC (analog-to-digital-converter) readings would be identical.
  3. Even though these two readings are 20us apart they can, for all intents and purposes, be regarded as having been taken at the same instant in time relative to the time taken for the puck to move.


Let’s now add a second serpentine winding such the induced waveform is a minimum when the yellow waveform is a maximum. We now have sine and cosine waveforms which can be sampled using A0 and A1. The phase angle can be calculated using the following formula:

  1. angle = atan2(sin, cos) ............................................... (1)


Measuring distance

  1. Mathematically it can be shown that:


  1. tangent = sine/cosine .................................................... (2)


  1. Two windings displaced by 90 degrees are required to calculate the tangent. If we connect the “sine” winding to Arduino pin A0 and the “cosine” winding to Arduino pin A1 we can calculate the position within each 4 inch “pitch” using the following formulas: [1] [2]


  1. angle = atan2(sine, cos) = atan2(A0,A1) ........................ (3)
  2. position = pitch*angle/360 ............................................. (4)


  1. And the horizontal position anywhere along the array using the following formulas


  1. angle = atan2(A0,A1) ....................................................... (5)
  2. accumulated_angle += angle2 – angle1 ......................... (6)
  3. distance = pitch*accumulated_angle/360 ...................... (7)


  1. The vertical position may be determined by connecting the vertical grids to Arduino pins A2.A3 and using the following formulas:


  1. angle = atan2(A2,A3) ......................................................... (8)
  2. accumulated_angle += angle2 – angle1 ........................... (9)
  3. distance = pitch*accumulated_angle/360 ........................(10)


If we now move the puck, the amplitude of the yellow waveform in fig.1, and the amplitude of the cosine waveform, will vary in a sinusoidal manner allowing us to calculate the distance travelled.


Note

[1]

The “pitch” is 4 inches when the serpentine “legs” are 2 inches apart.


[2]

It’s not possible to simultaneously sample A0 and A1 ... the best we can do is sample A0 then sample A1 20us later. The fact that we are NOT sampling A0 and A1 at the same time doesn’t matter as:


  1. 20us is an insignificant fraction of the time taken to move the puck across the grid.


Example:

Time to move puck = 1 second =1000000us

Time between samples = 20us

Error =360*20/1000000 = 0.0072 degrees

Software

The following software packages are required if you wish to view your puck motion on screen:


  1. The Arduino IDE (integrated development environment) that is available from https://www.arduino.cc/en/software/


  1. Processing 4 which is available from https://processing.org/download


  1. electromagnetic_graphics_tablet_v2.ino .......... (Arduino tablet code)


  1. electromagnetic_graphics_tablet_v2.pde .......... (Processing code to view the puck motion)


Installation

  1. Download and install each of the above packages. The electromagnetic_graphics_tablet_v2 packages are attached.


  1. Copy the contents of “electromagnetic_graphics_tablet_v2.ino” into a fresh Arduino sketch, save, then compile and upload the sketch to your arduino. Use a text editor such as Notepad++ when copying ... not a word processor.


  1. Copy the contents of “electromagnetic_graphics_tablet_v2.pde” into a fresh Processing sketch and save. Use a text editor such as Notepad++ when copying ... not a word processor.

Operation

processing output.png

The Arduino IDE is no longer required once electromagnetic_graphics_tablet_v2 has been installed on your Arduino.


Simply power up your Arduino and switch on the battery supply to your puck.


To view your puck movement:

  1. Launch Processing ... the same as you would the Arduino IDE


  1. Open electromagnetic_graphics_tablet_v2


  1. Place the cross-hairs of your puck over the tablet (0,0) coordinate


  1. Click the triangular Processing run button ... a graphics screen will appear.


  1. Wait until the numbers in the top-left corner of the graphics screen start changing then slowly move your mouse ... the numbers indicate your XY coordinate position.


  1. Press the puck button to create a line ... release the puck button to stop drawing.


  1. Click the square Processing stop buttonto exit.


Output Files

Two files are created in your Processing folder when you exit:

  1. capture.csv ... your data in spreadsheet format.
  2. output.nc ... your data in numerical control format.


The location of these files is shown in fig.1


Notes

[1]

Only one ADC can be active at a time BUT we can effectively obtain simultaneous sampling by sequentually sampling each waveform at 20us (microsecond) intervals.


This is possible because the ADC processing time is only 13us and each waveform is synchronised to a common pulse.

Calibration

calibration.jpg
cal1.png
cal2.png
raw data.png
table_from_ raw curves.png

In theory, calibration is not required.


In practice, the magnetic field from the puck spreads out in all directions. This means small currents are induced in nearby wires, which causes the zero-crossing points in each grid to shift slightly closer together which is the reason the diagonals in fig.4 have wobbles.


Fortunately this distortion can be corrected with a linearisation table.


The screen shot shown in fig.5 was obtained using a 21 point linearisation table.

Larger linearisation tables will result in smoother lines.



Working Area and Layout

The 10" × 10" square outlined in black in Fig. 1 is your working area. Around this is a 2-inch border, known as a guard band. This ensures that the puck is always positioned between:

  1. one sine grid wire, and
  2. one cosine grid wire

If this condition is not met, the system will not work correctly.


The crosshair inside the puck is over the (0, 0) starting position.

The wires connecting the grid to the Arduino are just visible in the top-left corner of the image.


Calibration

The following example shows how to create a 21-point linearisation table.

You can use the same method to create larger tables.


Step-by-Step

  1. Place the puck at the (0, 0) starting position.


  1. Open your arduino Serial Monitor You should see data similar to Fig. 2 appear in the Serial Monitor.


  1. Copy the first xPosRaw value into the first position of measuredTableX[NUM_XPOINTS]


  1. Move the puck horizontally 12.7 mm (0.5 inches) and copy the new xPosRaw value into the next position.


  1. Repeat this process until the measuredTableX table is complete.


  1. Copy the first value from measuredTableX into the first position of expectedTableX[NUM_XPOINTS]


  1. Fill the rest of expectedTableX by adding 12.7 mm each step until the table is complete.


  1. Repeat the entire process for the Y-axis using yPosRaw values (see Fig. 3), to fill the measuredTableY[NUM_XPOINTS]


  1. Copy the first value from measuredTableY into the first position of expectedTableY[NUM_XPOINTS]


  1. Fill the rest of expectedTableY by adding 12.7 mm each step until the table is complete.


  1. Once both tables are complete, comment out #define CALIBRATE in the header then compile and upload the code to your Arduino


  1. Done.

Summary

This instructable explains how to make a simple electromagnetic graphics tablet that tracks the position of a handheld “puck” and displays its position on screen.


This project is a proof of concept, but it produces consistent and repeatable results even with manual construction.


The accuracy, while not perfect, is excellent.


The system uses:

  1. Two wire grids arranged at right angles
  2. A small puck that generates a signal
  3. An Arduino UNO to read and process the signals


As the puck moves, the tablet calculates its position based on how the signal is picked up by the wire grids.


Construction is simple ... all you require is:

  1. a sharp knife,
  2. a pair of side-cutters,
  3. a small screwdriver,
  4. a soldering iron,
  5. and access to a 3D printer.


All construction details, including code and STL files for 3D printing, are provided.


The estimated cost, excluding postage, is less than $80.00


  Click here   to view my other instructables.