Freesteel Blog » Machining music

Machining music

Saturday, August 13th, 2016 at 12:23 pm Written by:

I’ve been getting some machining done, found out what worn out tools are like when you try to use them, and bought a whole load more.

We’ve also been doing some important work controlling servos directly from the Beagleboard through an H-bridge which will allow us to bypass the conventional servo motor drive setup that prevents all positional feedback information.

You can see the varying width modulations on the scope here:


The code, compiled from C and deployed on the programmable realtime unit, varies the pulse width every cycle thus modulates the amplitude like a class D amplifier.

The music, in the second half of the above video, isn’t well picked up by the phone microphone, although it sounded surprisingly good in reality.

This is almost all the PRU code responsible for reading the channels (pairs of numbers that are wavelength and amplitude) and setting the PWM width per cycle.

struct Commondata {  unsigned int notes[NOTECHANNELS*2];  };
volatile near struct Commondata commondata __attribute__((cregister("PRU_DMEM_0_1", near), peripheral));

int main() 
  CT_ECAP.ECCTL2 = 0x02C0;
  CT_ECAP.CAP1 = 4096;    // PWM clock period
  CT_ECAP.ECCTL2 |= 0x0010;

  long channelcounts[NOTECHANNELS];
  for (int i = 0; i < NOTECHANNELS; i++) 
    	channelcounts[i] = 0;

  int mid50 = CT_ECAP.CAP1/2;
  int guardlo = mid50/8;   // clock range safe to change
  int maxamplitude = mid50 - guardlo;


    int waveamp = 0;
    for (i = 0; i < NOTECHANNELS; i++) {
      if ((pid.notes[i*2] == 0) || (pid.notes[i*2+1] == 0))
      channelcounts[i] -= 16;  // granularity of steps per PWM cycle
      if (channelcounts[i] < 0)  // countdown crosses zero, set wave back up
        channelcounts[i] += pid.notes[i*2];

      // calculate sawtooth wave amplitude within period
      int amp = (pid.notes[i*2+1] * channelcounts[i]) / pid.notes[i*2] - pid.notes[i*2+1] / 2;
      waveamp += amp;   // sum up the amplitudes

    // attenuate rather than truncate
    waveamp = waveamp*maxamplitude/(abs(waveamp) + maxamplitude);

    // wait till we are outside of the lower values of the clock
    while (CT_ECAP.TSCTR < guardlo)
    // wait till the clock has ticked over (but hasn't counted above 100)
    while (!(CT_ECAP.TSCTR < guardlo))

    // set the next duty cycle length (safe as value greater than guardlo)
    CT_ECAP.CAP2 = waveamp + mid50;

It's about 50 times less code and effort than I thought it was going to be, mainly due to the use of the PWM subsystems, rather than attempting to generate timed PWM in realtime from the PRU code. This could only have been possible were I authoring the assembly code directly instead of using a compiler, because only that way can you count the cycles. This is a good move because, while it would have been fun to write carefully hand-coded division routines that used a fixed amount of processor cycles, it would have been a waste of my time. This way we're simply using the PRUs as co-processors that we assume are running fast enough to service those other subsystems in the chip.

The other subsystem we need to read are the quadrature encoders in order to drive the motors to a given position -- and read what position they have been dragged to by other forces (like human hands).

This is the current state of the project plan to get to a milling machine that responds to cutting forces with changes in toolpath trajectory (which requires the abolition of G-code).

It's all about us keeping an eye on where we are trying to get to, picking the route to it that takes us across the known unknowns in a way that exposes us to maximum learning, and then cutting corners (eg by further bodging the circuits we already have).

I couldn't do this if I had to explain, repeat and clear every change of plan with a boss who was remote to the project.

On the other hand, if we did have a boss maybe we'd get there at the same rate on account of a lot fewer holidays per year.

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <blockquote cite=""> <code> <em> <strong>