Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

wobbling polygon motor

Status
Not open for further replies.

BraveWart

Member
I am working on a project where I have to pulse a laser against a spinning, six sided polygon mirror motor.
https://www.precisionroller.com/motors-for-sharp-mx-3640n/products.html
(worth noting that i have them from china)
I am pulsing at the motor frequency x6 to get a single laser dot reflected of the mirrors.
The motor is receiving a PWM signal from an Arduino. The laser is receiving a 6x that frequency signal with a very small duty cycle.

For this I am using code that generates very precise pwn signals using ticks of the internal PWM clock. The signals are verified on my scope and are constant and in sync.

So far so good. I am getting my desired laser dot in the target area.
The problem is that the dot is wobbling back and forth.
I am on this project with a colleague who helped with all of this and made this video for him.
laser wobble

We cant figure out why that wobble happens.
These motors are used in laser printers and scanners and must spin with high precision.
We tried all kinds of things to make it steady. Hence the custom code for the PWM signals.

I have tried:
  • using different signal sources in case there is a problem with aligning both signals
  • hardware and software PWM's
  • i hooked up an led to the laser signal and illuminated the spinning motor in a dark room. I could clearly see the edge of the mirror wobble in the same pattern as on the laser dot
  • I blew air on the motor while doing the led test. That made the mirror wobble even more
  • I own 3 different polygon motors of different brands. they all show the same behaviour
What could it be?
Is the motor broken? But all three of them?
Is it air turbulence? But that is also hard to believe since these motors sit in open spaces inside printers. If anything, then air turbulence would be worse in there.

Any tips on what that could be are well appreciated


This is the code we are using to create both PWM signals:

C++:
#include <TimerHelpers.h>


const byte intcheck = 8;
const byte timer1OutputA = 9;
const byte timer1OutputB = 10;
volatile uint8_t pulse_count = 0;


bool LED_STATE = true;


void setup() {


   pinMode (timer1OutputA, OUTPUT);
   pinMode (timer1OutputB, OUTPUT);
   pinMode (intcheck, OUTPUT);
    cli();
  TCCR1A = 0;                 // Reset entire TCCR1A to 0
  TCCR1B = 0;                 // Reset entire TCCR1B to 0
     /*3. We enable compare match mode on register B*/
  TIMSK1 |= B00000100;        //Set OCIE1B to 1 so we enable compare match B

   Timer1::setMode (15, Timer1:RESCALE_8, Timer1::CLEAR_A_ON_COMPARE | Timer1::CLEAR_B_ON_COMPARE);
   OCR1A = 4000;
   OCR1B = 5;
  sei();                     //Enable back the interrupts
}  // end of setup

void loop() {}

ISR(TIMER1_COMPB_vect){

    if (pulse_count < 2) {

        pulse_count++;
    } else {
        pulse_count = 0;
        PORTB ^= (1 << PB0); // toggle pin 8 (PB0)
     
    }
}

and this is temerhelpers.h:
C++:
/*
 Timer Helpers library.

Devised and written by Nick Gammon.
Date: 21 March 2012
Version: 1.0

Licence: Released for public use.
 
See: http://www.gammon.com.au/forum/?id=11504
 
 Example:
 
 // set up Timer 1
 TCNT1 = 0;         // reset counter
 OCR1A =  999;       // compare A register value (1000 * clock speed)
 
 // Mode 4: CTC, top = OCR1A
 Timer1::setMode (4, Timer1::PRESCALE_1, Timer1::CLEAR_A_ON_COMPARE);
 
 TIFR1 |= bit (OCF1A);    // clear interrupt flag
 TIMSK1 = bit (OCIE1A);   // interrupt on Compare A Match 
 
*/

#ifndef _TimerHelpers_h
#define _TimerHelpers_h

#if defined(ARDUINO) && ARDUINO >= 100
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif

/* ---------------------------------------------------------------
 Timer 0 setup
 --------------------------------------------------------------- */

namespace Timer0
{
  // TCCR0A, TCCR0B
  const byte Modes [8] [2] =
  {
 
  { 0,                         0 },            // 0: Normal, top = 0xFF
  { bit (WGM00),               0 },            // 1: PWM, Phase-correct, top = 0xFF
  {               bit (WGM01), 0 },            // 2: CTC, top = OCR0A
  { bit (WGM00) | bit (WGM01), 0 },            // 3: Fast PWM, top = 0xFF
  { 0,                         bit (WGM02) },  // 4: Reserved
  { bit (WGM00),               bit (WGM02) },  // 5: PWM, Phase-correct, top = OCR0A
  {               bit (WGM01), bit (WGM02) },  // 6: Reserved
  { bit (WGM00) | bit (WGM01), bit (WGM02) },  // 7: Fast PWM, top = OCR0A
 
  };  // end of Timer0::Modes
 
  // Activation
  // Note: T0 is pin 6, Arduino port: D4
  enum { NO_CLOCK, PRESCALE_1, PRESCALE_8, PRESCALE_64, PRESCALE_256, PRESCALE_1024, T0_FALLING, T0_RISING };
 
  // what ports to toggle on timer fire
  enum { NO_PORT = 0,
    
    // pin 12, Arduino port: D6
    TOGGLE_A_ON_COMPARE  = bit (COM0A0),
    CLEAR_A_ON_COMPARE   = bit (COM0A1),
    SET_A_ON_COMPARE     = bit (COM0A0) | bit (COM0A1),
    
    // pin 11, Arduino port: D5
    TOGGLE_B_ON_COMPARE  = bit (COM0B0),
    CLEAR_B_ON_COMPARE   = bit (COM0B1),
    SET_B_ON_COMPARE     = bit (COM0B0) | bit (COM0B1),
  };
 
 
  // choose a timer mode, set which clock speed, and which port to toggle
  void setMode (const byte mode, const byte clock, const byte port)
  {
  if (mode < 0 || mode > 7)  // sanity check
    return;
 
  // reset existing flags
  TCCR0A = 0;
  TCCR0B = 0;
 
  TCCR0A |= (Modes [mode] [0]) | port; 
  TCCR0B |= (Modes [mode] [1]) | clock;
  }  // end of Timer0::setMode
 
}  // end of namespace Timer0

/* ---------------------------------------------------------------
 Timer 1 setup
 --------------------------------------------------------------- */

namespace Timer1
{
  // TCCR1A, TCCR1B
  const byte Modes [16] [2] =
  {
 
  { 0,                         0 },            // 0: Normal, top = 0xFFFF
  { bit (WGM10),               0 },            // 1: PWM, Phase-correct, 8 bit, top = 0xFF
  {               bit (WGM11), 0 },            // 2: PWM, Phase-correct, 9 bit, top = 0x1FF
  { bit (WGM10) | bit (WGM11), 0 },            // 3: PWM, Phase-correct, 10 bit, top = 0x3FF
  { 0,                         bit (WGM12) },  // 4: CTC, top = OCR1A
  { bit (WGM10),               bit (WGM12) },  // 5: Fast PWM, 8 bit, top = 0xFF
  {               bit (WGM11), bit (WGM12) },  // 6: Fast PWM, 9 bit, top = 0x1FF
  { bit (WGM10) | bit (WGM11), bit (WGM12) },  // 7: Fast PWM, 10 bit, top = 0x3FF
  { 0,                                       bit (WGM13) },  // 8: PWM, phase and frequency correct, top = ICR1   
  { bit (WGM10),                             bit (WGM13) },  // 9: PWM, phase and frequency correct, top = OCR1A   
  {               bit (WGM11),               bit (WGM13) },  // 10: PWM, phase correct, top = ICR1A   
  { bit (WGM10) | bit (WGM11),               bit (WGM13) },  // 11: PWM, phase correct, top = OCR1A
  { 0,                         bit (WGM12) | bit (WGM13) },  // 12: CTC, top = ICR1   
  { bit (WGM10),               bit (WGM12) | bit (WGM13) },  // 13: reserved
  {               bit (WGM11), bit (WGM12) | bit (WGM13) },  // 14: Fast PWM, TOP = ICR1
  { bit (WGM10) | bit (WGM11), bit (WGM12) | bit (WGM13) },  // 15: Fast PWM, TOP = OCR1A
 
  };  // end of Timer1::Modes
 
  // Activation
  // Note: T1 is pin 11, Arduino port: D5
  enum { NO_CLOCK, PRESCALE_1, PRESCALE_8, PRESCALE_64, PRESCALE_256, PRESCALE_1024, T1_FALLING, T1_RISING };
 
  // what ports to toggle on timer fire
  enum { NO_PORT = 0,
    
    // pin 15, Arduino port: D9
    TOGGLE_A_ON_COMPARE  = bit (COM1A0),
    CLEAR_A_ON_COMPARE   = bit (COM1A1),
    SET_A_ON_COMPARE     = bit (COM1A0) | bit (COM1A1),
    
    // pin 16, Arduino port: D10
    TOGGLE_B_ON_COMPARE  = bit (COM1B0),
    CLEAR_B_ON_COMPARE   = bit (COM1B1),
    SET_B_ON_COMPARE     = bit (COM1B0) | bit (COM1B1),
  };
 
  // choose a timer mode, set which clock speed, and which port to toggle
  void setMode (const byte mode, const byte clock, const byte port)
  {
  if (mode < 0 || mode > 15)  // sanity check
    return;
 
  // reset existing flags
  TCCR1A = 0;
  TCCR1B = 0;
 
  TCCR1A |= (Modes [mode] [0]) | port; 
  TCCR1B |= (Modes [mode] [1]) | clock;
  }  // end of Timer1::setMode
 
}  // end of namespace Timer1

/* ---------------------------------------------------------------
 Timer 2 setup
 --------------------------------------------------------------- */

namespace Timer2
{
  // TCCR2A, TCCR2B
  const byte Modes [8] [2] =
  {
 
  { 0,                         0 },            // 0: Normal, top = 0xFF
  { bit (WGM20),               0 },            // 1: PWM, Phase-correct, top = 0xFF
  {               bit (WGM21), 0 },            // 2: CTC, top = OCR2A
  { bit (WGM20) | bit (WGM21), 0 },            // 3: Fast PWM, top = 0xFF
  { 0,                         bit (WGM22) },  // 4: Reserved
  { bit (WGM20),               bit (WGM22) },  // 5: PWM, Phase-correct, top = OCR2A
  {               bit (WGM21), bit (WGM22) },  // 6: Reserved
  { bit (WGM20) | bit (WGM21), bit (WGM22) },  // 7: Fast PWM, top = OCR2A
 
  };  // end of Timer2::Modes
 
  // Activation
  enum { NO_CLOCK, PRESCALE_1, PRESCALE_8, PRESCALE_32, PRESCALE_64, PRESCALE_128, PRESCALE_256, PRESCALE_1024 };
 
  // what ports to toggle on timer fire
  enum { NO_PORT = 0,
    
    // pin 17, Arduino port: D11
    TOGGLE_A_ON_COMPARE  = bit (COM2A0),
    CLEAR_A_ON_COMPARE   = bit (COM2A1),
    SET_A_ON_COMPARE     = bit (COM2A0) | bit (COM2A1),
    
    // pin 5, Arduino port: D3
    TOGGLE_B_ON_COMPARE  = bit (COM2B0),
    CLEAR_B_ON_COMPARE   = bit (COM2B1),
    SET_B_ON_COMPARE     = bit (COM2B0) | bit (COM2B1),
  };
 
 
  // choose a timer mode, set which clock speed, and which port to toggle
  void setMode (const byte mode, const byte clock, const byte port)
  {
  if (mode < 0 || mode > 7)  // sanity check
    return;
 
  // reset existing flags
  TCCR2A = 0;
  TCCR2B = 0;
 
  TCCR2A |= (Modes [mode] [0]) | port; 
  TCCR2B |= (Modes [mode] [1]) | clock;
  }  // end of Timer2::setMode
 
}  // end of namespace Timer2

#endif
 
Last edited:
Just from Google.



very interesting. as per calculation above, 50000 RPM would make up for 833 Hz.
If the above solution works, we will gradually go higher. The datasheet of the IC also indicates that the motor will cut out if it goes above a set base frequency, so i guess it should be safe.
 
It looks to me as if CLK, LD and S/S go to testpoints 13, 14 & 15 respectively, though it's not easy to trace them.

From there they go to pins 1 - 3 in some order; it looks like CLK is pin 1, not sure about the others.

If you are using pin 3 to control it, then that's S/S, the motor enable pin.

If I'm right, it is only ever free-running without a clock signal going to pin 1 to synchronise it. That ties in with the noisy signal from LD, it's never able to lock up in sync with anything.

ps. 250 Hz (Facet speed) is 2500 RPM, that's not all that slow, though I have no idea what the full working speed should be.

The lack of clock and having the power enable switched all the time could explain some of the noise you mention, as the torque will be increasing and decreasing with every enable pulse, causing vibration.
I ran some tests on all motors.
giving pin4 GND and pin5 24V
Pin 1 = 23V
Pin 2 = 5V
Pin 3= 24V
then I applied CLK to pin 1 (measured the square wave from the socked pin on pin1, looking ok)
nothing happens as expected.

put pin 3 to GND
this had the same result on all motors with slightly different effects.

the first motor started to spin but the the power supply cut out. I had it set to 0.9A. Raised it to 1A. Still cut out.
But: when it started spinning I could already tell it had a smoother ring to it.

The second motor doesnt cut out the power supply, but it starts and stops kind of jittery. Same for the third motor.
I made this video: https://photos.app.goo.gl/CxMgmhaMySkPsBJN8

I also tried pin2 to 5V or GND and that didnt do anything.

In the end I tried to replicate the power cut issue on motor 1 and I couldn't replicate it. It now also stutters.
 
OK, it may be in needs either a higher or lower clock frequency?

Or, at full power the motors just need more than the PSU can give?
I can give more amps. I think up to 5, or 10. I dont remember. Will have to check. But when we did our initial tests with the motors, my colleague didnt want to go above 1A if we didnt have to. Can I theoretically blow it?
I didnt even think about the CLK speed. Will try that too.
 
That is correct. There is no feedback from the motor and our assumption was that it runs precise. (just my own assumption actually)
We never found any datasheets of these devices. There is one pin that provides a signal out, but the acquired signal was very very noisy and it also seemed to be directly linked to the input signal. If it were a feedback signal, I would have expected to ramp up as the motor spins up and ramp down as the motor spins down. But it was art a constant towards the input signal even during spin up and down phases. The assumption then was that it must be a stray signal and not a feedback signal on the actual rotation speed.
So you are saying, the wobble is likely an expected behaviour and must normally be compensated through a feedback signal of the actual speed?
How did you look at the feedback signal?

It sounds like you were using a voltmeter to see a ~dc voltage with some noise on it. It is probably either a pulse string or even a sine wave, that may be riding on top of a DC voltage.

To see the true nature of the signal, you'll need an oscilloscope.
 
How did you look at the feedback signal?

It sounds like you were using a voltmeter to see a ~dc voltage with some noise on it. It is probably either a pulse string or even a sine wave, that may be riding on top of a DC voltage.

To see the true nature of the signal, you'll need an oscilloscope.
I use an oscilloscope. I just went through my photo library and found these:
https://photos.app.goo.gl/RB6wDteort4ioDf89
PXL_20230212_133633963.jpg
unfortunately I didnt label the photos, so I am not 100% sure which one was that signal.
I will try to think of making another video when I try again tonight.
 
A bit frustrating. I tried it again and was kind of positive this should work as with all the above comments this is what makes the most sense. Unfortunately it keeps fizzing out when I pull pin3 to LOW. I made this video:
video
I also tried it on the other unused motor. It's a different chip and I think pin 2 is CLK on that one as pin1 & 3 are 5V. pulling pin3 LOW has the exact same effect as on the motor in the video.
I also tried pin2 on the motor in the video and it seems to give or do nothing. Might be the lock signal once its spinning?
 
Try about 130Hz; it may be that 200 - 250 is just to high for it to run at.

I found some outline specs for a Mitsumi version; it says 50,000 but no mention of "RPM" - I think that may be scans per minute, so 6x motor RPM.

If that's the case, the top RPM sync would be around 138 Hz.
For a 40,000 one it would be around 110 Hz.
 
Try about 130Hz; it may be that 200 - 250 is just to high for it to run at.

I found some outline specs for a Mitsumi version; it says 50,000 but no mention of "RPM" - I think that may be scans per minute, so 6x motor RPM.

If that's the case, the top RPM sync would be around 138 Hz.
For a 40,000 one it would be around 110 Hz.
forgot to mention that i tried a variety of frequencies from 50Hz, 100, 160 and 400 too. It reacted all the same
 
Quick update. I could attend to this for a while, but tried it again today.
I got it working on the one motor that we have the datasheet.
pin1: CLK
pin2: ?
pin3: SS -> pull low
pin4: GND
pin5: V
For CLK I needed to apply 2kHz for it to work. It runs smooth and steady. I dont quite understand why the high frequency is required. I can't possibly spin this fast. So it must be some sort of control signal and not the actual spin frequency?

I havent tried so synchronise it with the laser yet as I am not sure a what actual speed the motor now spins. But I expect the wobble to be gone now.

Thank you everyone @rjenkinsgb, @shortbus= for helpinmg with this.
 
I havent tried so synchronise it with the laser yet as I am not sure a what actual speed the motor now spins.

Just a dumb thought. Would the laser need to be synchronized? I always thought that was the reason for the polygon rotating mirrors, to get rid of the synchronization. Flashing a laser fast seems like it would be harder than pointing a steady beam at a rotating mirror array, to get a flashing signal.
 
Good question. For our project we want to sample a photodiode with the laser scanning the full angle of a facet of the mirror and then detect an object within that scan field. one step on the way to this was to try to pulse the laser to a specific spot in the target area. That pulse would need to be motor_frequency x 6. Ultimately this test is what showed us there is a problem with the spin consistency.
But you are right. We might not need to do this in the final setup. My colleague is the one who comes up with the test parameters. I think next is to setup the PD and see what we get back in terms of reflected light from the laser
 
The "FGS" pin on the IC is the sync signal out.

In the original laser printer use, the print controller must know when each scan starts to synchronise the dot pattern timing for that scan line, so it should be there somewhere - possibly connector pin 2??
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top