Millis() and Micros() for 8Bits

Go To Last Post
36 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey Guys

I would like to know if there's already an existing library for Atmel C Millis() and Micros() like the Arduino has?
I figured that it's obviously possible since Arduino is essentially wrapped up Atmel MUCs.

If there isn't any and I would like to create my own. Will it be possible to have a 10uS interrupt to set up a flag which will then increment a Unsigned Long?

Or will this Tax the MCU to much and render it useless for all the other processes that it should be doing? In which case I will rather create a 1mS interrupt.

Also. I notice that allot of the usual Atmel 8Bit MCUs only go to roughly 16Mhz Clock speed. 1/16000000 wont really give me smaller then Micro Seconds so I guess that wont happen anytime soon.
I had the same thing on MicroChip but it was going at 40Mhz.

Is there any way I can manipulate the an Atmel 8bit MCU to be able to give me atleast 10uS Interrupts?

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I had the same thing on MicroChip but it was going at 40Mhz.

Which is a meaningless comparison unless you take into consideration the number of clock cycles each machine instruction takes on the different architectures.

Since one instruction takes one to three clocks on an AVR, and a number of instructions are executed for the "entry, body and exit" of an ISR I have a hard time seeing how you can get a resolution of 1 microsecond.

I don't think the Arduino framework sports that resolution, but for the details why not simply look at their code?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As far as I can remember, the Arduino Timer 0 uses a 4us 'tick'. It overflows at 250 ticks to increment millis() in CTC mode.
micros() are simply (millis() * 1000) + (TCNT0 * 4)

As Johan says, look at the source code. I have not !

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Perhaps you can explain your goal here.

From the Arduino doc for Millis and Micros I'd speculate that there is a 1ms heartbeat timer. The servicing for that isn't onerous. Further speculation is that a call to Micros() uses the accumulated millis value and adds the timer counts for the partial.

(It could also be e.g. a 10ms heartbeat, and both Millis and Micros calls use partials.)

No matter, really, as you aren't interested in using Arduino framework per se, but rather trying to do fine timing.

The short answer: An AVR program can time short intervals of external events down to the resolution of one AVR clock. That is typically sub-microsecond, using ICP.

On a more general basis, let's say the AVR is running at 16MHz. A 16-bit timer running at /1 would take 16000 counts for a millisecond. As mentioned, servicing that interrupt might not be too bad, with some care. Call that the "whole" milliseconds.

At any time, you can read TCNT1; that is the "partial" in 66ns ticks.

Now, how fast can you get to that TCNT1 read after the interesting event occurs? Only ICP will not have any latency. Beyond that, it depends on your app (how many ISRs might be enabled and when they might hit), and your programming skill. In a mostly free/idle app except for the important event, the start and end latency might well balance out.

This thread might be interesting for you--multi-channel "Pinewood Derby" timer.
https://www.avrfreaks.net/index.p...

Beyond that, tell more about the app needs.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can time sequences down to 1 cycle resolution by simply starting and stopping TCNT1. You can process the result at leisure. (the stopped timer does not alter or generate any more interrupts)

Yes, it is sometimes interesting to compare different Compilers or code sequences.
In practice, you just write straightforward code and never worry about it.

void init_us(void);
int calc_us(void);
#define _FUNCTIME(f, msg)	{f; }
#define STDFUNCTIME(f, msg)	{printf(msg); init_us(); f; calc_us();}

I just add "functime.h" and "functime.c" to my project.
If I was anal, I suppose that I could have a calc_ns() function.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Will it be possible to have a 10uS interrupt to set up a flag which will then increment a Unsigned Long? ... Is there any way I can manipulate the an Atmel 8bit MCU to be able to give me atleast 10uS Interrupts?
At 16MHz an interrupt every 10us gives you 160 cycles to work with (and most modern AVRs can go up to 20MHz). So there is plenty of time to set a flag and increment a number. Wether or not there is time outside of the interrupt to do anything with that number depends on what you want to do with it and whether you need to do that something every time the interrupt occurs.
Quote:
I can time sequences down to 1 cycle resolution by simply starting and stopping TCNT1. You can process the result at leisure.
But I don't think that is anything like what the OP wants.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The MCU thats incrementing the nSeconds will be switching a pin On and Off depending on the signal it gets from a controlling MCU.

Unfortunately it has to be in the 1uS to 100uS range.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

The MCU thats incrementing the nSeconds will be switching a pin On and Off depending on the signal it gets from a controlling MCU.

Unfortunately it has to be in the 1uS to 100uS range.


You aren't telling much. Like a command over a UART link that says "pulse pin for 42us"? If so, not really a problem with a timer in CTC or PWM mode.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suggested how you can implement Millis(). i.e. copy the Arduino.

The Arduino Micros() is pants in terms of accuracy. The maths involved will affect the timing. However, I presume you just want a sort of System Timer. The Arduino will have a resolution of 4us. Is that good enough ?

I showed a method for timing anything very accurately. Timer1 is not used by the Arduino.

If you want to generate a pulse, the Arduino has a method() for this. Or you write your own one.

Note that you can use 16MHz div8 to give you 500ns ticks. Then you count 8 overflows before incrementing millis().
It does give you a bigger overhead. i.e. interrupt every 125us instead of every 1000us.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you saying you need to switch a pins state with microsecond resolution?

You do not need a counter variable with microsecond resolution to do that.

Use a timer - i.e. no software variable, but a hardware Timer/Counter.

Details can be discussed when you give a detailed description of what you want to accomplish. Don't describe a (possibly non-workable) solution (like #I need a variable that increments..."), but what you really need to accomplish.

Generally: By selecting main clock frequency and timer/counter prescaler wisely you can accomplish microsecond resolution, and close to microsecond accuracy. Let's say this is a 16-bit timer. Set TOP = 1000 so that the timer interrupts every millisecond, whereupon you decrease the desired time in microseconds by 1000. When the remaining desired time goes below 1000 you set TOP to the remaining value. Next time the ISR activates, the time has elapsed.

The devil is in the details. If the desired time is e.g. 20001 microseconds, the remaining number of microseconds for the last "round" is 1 millisecond - before you've set that value as TOP it might be that the timer already has counted past 1. If so the timer will continue counting through all 16 bits before it wraps and finally hits 1 - but that will be 64K timer ticks too late! Some tinkering with how you treat the two last rounds might be needed. So far resolution.

For accuracy, you will never have enough control of the code executed to be guaranteed that you get to microsecond accuracy. For that you will need to resort to assembler and very carefully crafted code.

Might we inquire what type of application needs switching a pin on and off with microsecond resolution and accuracy?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
As far as I can remember, the Arduino Timer 0 uses a 4us 'tick'. It overflows at 250 ticks to increment millis() in CTC mode.
micros() are simply (millis() * 1000) + (TCNT0 * 4)
Close. On the 88/168/328, TIMER0 is set to mode 3, fast PWM, with prescaler 64. At 16 MHz, this gives an overflow interrupt every 1024 uS. The ISR updates three volatiles:
volatile unsigned long timer0_overflow_count = 0;
volatile unsigned long timer0_millis = 0;
static unsigned char timer0_fract = 0;

SIGNAL(TIMER0_OVF_vect)
{
	unsigned long m = timer0_millis;
	unsigned char f = timer0_fract;

	m += MILLIS_INC;
	f += FRACT_INC;
	if (f >= FRACT_MAX) {
		f -= FRACT_MAX;
		m += 1;
	}

	timer0_fract = f;
	timer0_millis = m;
	timer0_overflow_count++;
}

... where MILLIS_INC, FRACT_INC, and FRACT_MAX are macros:

#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) )
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
// the fractional number of milliseconds per timer0 overflow. we shift right
// by three to fit these numbers into a byte. (for the clock speeds we care
// about - 8 and 16 MHz - this doesn't lose precision.)
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
#define FRACT_MAX (1000 >> 3)

... and the function millis() simply returns the value of timer0_millis:

unsigned long millis()
{
	unsigned long m;
	uint8_t oldSREG = SREG;

	cli();
	m = timer0_millis;
	SREG = oldSREG;

	return m;
}

The function micros() is somewhat more involved:

unsigned long micros() {
	unsigned long m;
	uint8_t oldSREG = SREG, t;
	
	cli();
	m = timer0_overflow_count;
	t = TCNT0;

  
	if ((TIFR0 & _BV(TOV0)) && (t < 255))
		m++;

	SREG = oldSREG;
	
	return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}

... and has a resolution of 4 uS at 16 MHz.

So, at the expense of an actual millis() resolution of 1024 uS, the two PWM channels on TIMER0 retain a full 8-bits of resolution for use by analogWrite(). For boards running at 8 MHz (like a Pro Mini 3.3V), millis() resolution drops to 2048 uS, and micros() resolution drops to 8 uS.

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cartman wrote:
If there isn't any and I would like to create my own.
I did the same for some ATtiny85 projects. I have millis(), micros(), and delay(), but not delayMicroseconds() (that is just a bad re-implementation of _delay_us() but with support for variable arguments), and they support every possible internally generated clock speed, from 500 Hz to 16 MHz, and all frequencies supported by a 32.768 KHz watch crystal, 128 Hz to 32.768 KHz. It should be easy to adapt them to any clock speed.

If you're interested, I can kick them to you via PM, or post them here, however it does seem from the rest of this thread that they won't really be an answer for you.

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes its going to be exactly like that...
In the Interrupt its going to have a function to check if its suppose to receive something...and if not it will continue pulsing at the old rate. BUT if it has change it will take a new course of action. This will simply be to set the new Pulsing rate.

As for Uart...Im still not really sure which one would work best.
Im am still really new to all this but setting little projects like this is how I learn best/fastest.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please do kick that code over to me Joeymorin :)
Well the application is a motor driver thats being controlled by the MCU. Problem is it wants its Pulses in uSeconds and WHY it wants this I have NO idea...But ive worked with it on the arduino and no matter how small I make the pulses the motor goes waaay to slow for the application to work as it should.

Its the WANTAI DQ542MA Stepper motor driver if anybody have worked with those in the past. Maybe im missing something.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cartman wrote:
Well the application is a motor driver thats being controlled by the MCU. Problem is it wants its Pulses in uSeconds and WHY it wants this I have NO idea...But ive worked with it on the arduino and no matter how small I make the pulses the motor goes waaay to slow for the application to work as it should.

Its the WANTAI DQ542MA Stepper motor driver if anybody have worked with those in the past. Maybe im missing something.

If you're having trouble getting this to work with Arduino, why would you think that re-implementing the Arduino timing infrastructure would solve your problem? It's sounding more and more like you need a more specific solution. I doubt that the generalized timing code I sent you will be of any help. It is after all just a more-generalized take on Arduino's 'wiring.c'.

You'll need to be more specific about what this driver wants to see, and how you'll be receiving commands from the other mcu you've mentioned. I suspect that a (probably dedicated) timer in CTC or PWM mode (as mentioned by @theusch), perhaps in conjunction with a slender ISR, is your best bet.

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Still missing a complete specs ow the requirements, I can only comment that Timer/Counter hardware on an AVR running at 16 MHz should be able to create pulses of 1/16 microsecond. That is, as in "a square wave of 8 MHz". If there are requirements of something like a PWM signal, then that changes things a bit. OTOH, there are (or where?) AVRs that had a PLL up the incoming clock to the Timer/Counters (to 48 MHz?) which should give you a duty cycle resolution of very close to 2 percent at 1 MHz PWM frequency.

No I won't Google that driver - please supply a link to where specs can be found.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Its the WANTAI DQ542MA Stepper motor driver if anybody have worked with those in the past. Maybe im missing something.

> DQ542MA Datasheet <

Hmm, where exactly did you read about the 10µS pulses? I couldn't find anything about pulse length! But it is a really sh#$ty datasheet though...

If your stepper isn't running properly it seems more to me like you didn't set up all those switches correctly, or maybe the wiring is wrong. Could be many things I think.

- Brian

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nothing in that data sheet about pulses short as a microsecond.

As I understand it you set the direction, and then pulse once for every step. Microsecond pulses would suggest on the order of 100K steps per second. For a 200 steps/rev stepper motor that would mean 500 rpm. I've heard of no stepper motor that does that.

Aside: It is interesting that the driver does not want signals at VCC level, but rather has its own "outs-and-ins" and the microcontroller side should make or break these circuits. (With e.g. a transistor or, as sketched in the data sheet, with an opto-coupler which might be wise since the motor voltage is between 18 and 50 Volts.)

You aren't simply connecting AVR output pins to the PUL+ and DIR+ terminals on the driver? That won't work.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
If you're having trouble getting this to work with Arduino, why would you think that re-implementing the Arduino timing infrastructure would solve your problem?

Well im hoping to have allot less overhead cause of the Arduino bootloader and also to try and actually get to uSeconds.
Note that I have only worked with the Arduino Uno and I cant manage to het a smaller on and off time on the Uno.
Also using the MCU alone with a clock and caps will greatly reduce the footprint on the board of the application. I know I can simply take off the MCU from the Arduino and implement it but I would like to gain more experience in the Raw Atmel coding form :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cartman wrote:
Well im hoping to have allot less overhead cause of the Arduino bootloader and also to try and actually get to uSeconds.
Note that I have only worked with the Arduino Uno and I cant manage to het a smaller on and off time on the Uno.
Also using the MCU alone with a clock and caps will greatly reduce the footprint on the board of the application. I know I can simply take off the MCU from the Arduino and implement it but I would like to gain more experience in the Raw Atmel coding form :)
But:
JohanEkdahl wrote:
Still missing a complete specs ow the requirements
... so...?

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

You aren't simply connecting AVR output pins to the PUL+ and DIR+ terminals on the driver? That won't work.

No I have 120ohm resistors between the MCU and the PUL+ and DIR+ ports.Then from the PUL- and DIR- ports a wire that goes to the MCUs Ground pin or any ground for that matter.
As I understand it, the driver has Opto-Couplers built in and im simply switching them on/off with the pulses.

I have played around with this controller for roughly a month now changing wires etc but no luck.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Still missing a complete specs ow the requirements

Ok Ill try and compile everything quickly..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

As I understand it, the driver has Opto-Couplers built in and im simply switching them on/off with the pulses.

I see it now. Schematics on page 3 and 4 misread by me.

Where did you get the specs on the microsecond pulses?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My month long search on how to get it working eventually led me to a person who has worked with these drivers for quite some time.

He told be that the only way he knew was to go as low as 5uS from an MCU. :s

He lives really far and is a really busy man so I do not bother him to much with all my questions and he does have right to Intellectual property which he doesn't want to share :(

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think we need to wind things back to the basics. These controllers look similar to the Leadshine brand - they probably all come out of the same factory. We don't know what motor you're using so we can't comment on power supply etc. I would suggest you look at the motor packages on www.oceancontrols.com.au and see what motor/driver package is closest to your setup. Look at what psu they offer and that should be what you want. Stepper motors need high peak currents in order to work well, so if your psu isn't up to the task you're going to have problems. There should also be information on the setup of the driver. Next thing to consider is that stepper motors don't like being run a speed without being accelerated. The noise the motor makes tells you if it is happy or not - if it is a graty sort of noise - it's missing steps so either the speed is too fast and/or too much load.If the motor is humming and turning, then it is most likely happy. In terms of the pulses you give to the driver, the magic value of 5us is the narrowest pulse it will accept. I would suggest you write a program that slowly sepeds up outputting pulses with a minimum width of 5us - make it 20 to be sure. You'll find out soon enough what the maximum speed is.

Why is the Arduino bootloader a problem? Apart from the startup time, it is out of the picture when your code runs.

There would have to be heaps of Arduino examples for driving stepper motors. I'd be starting there first, then work towards your own solution.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Let's see...

The Arduino bootloader is "not in the picture" when running the sketch.

The Arduino "digitalWrite" function is slow enough (20+ cycles) that getting pulses with widths of small numbers of microseconds would be difficult. Arduino sketches don't need to restrict themselves to digitalWrite, though...

The Arduino micros() function has a resolution of about 4us. delayMicroseconds() is ... not very accurate for small values or unusual clockrates.

I don't know why the arduino libraries don't use the avr-libc _delay macros internally. They've long since thrown away any "simplicity" that might have been gained by using the timers. :-( Probably fear of change...

Whether you can step a stepper motor at at 10us per step is going to be highly dependent on the motor.

For best performance, you REALLY don't want to constrain your delay routines to accurately measuring "microseconds"; you want to operate on some multiple of the actual clockrate. If you can convert an absolute time to a number of cycles/instructions at compile time (like the avr-libc _delay functions), that's great. Saying "my 20MHz AVR with the Arduino libraries generates a clock tick every 3.2 microseconds, so I could convert that to actual microseconds by multiplying by 32 (doable with shift!) and dividing by 10" is ridiculous.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

99.9% of the people who think they need delays actually just need an extra timer interrupt.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hugoboss wrote:
99.9% of the people who think they need delays actually just need an extra timer interrupt.
That's only true 73.4% of the time ;)

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think it must be this one " http://oceancontrols.com.au/SMC-... "

Although it's not the same name but its exactly the same driver. I don't really know if its the power supply cause its correctly rated at 4 amps and Im driving a 3 amp motor...or atleast it is set to 3Amp.

But I will have to try code a 10uS timer and then just make it go faster and faster and see if it works like intended.

Even on those specs my Stepper motor and driver is setup right.
I literally think that I just need a 5uS+ on and off timer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cartman wrote:
I think it must be this one " http://oceancontrols.com.au/SMC-... "

Looks like it is the same thing!

Quote:
But I will have to try code a 10uS timer and then just make it go faster and faster and see if it works like intended.

Even on those specs my Stepper motor and driver is setup right.
I literally think that I just need a 5uS+ on and off timer.

"For reliable response, pulse width
should be longer than 2.5μs."

Also:

"To prevent noise incurred in PUL/DIR signal, pulse/direction signal wires and motor wires should not be tied up together. It is better to separate them by at least 10 cm, otherwise the disturbing signals generated by motor will easily disturb pulse direction signals, causing motor position error, system instability and other failures."

I don't see anywhere in this datasheet either, that says that you have to use pulses in the few µS range. Actually they warn you against using pulses that are too short..! I don't even see anywhere that there is a maximum pulse width! For all I know you could use hour long pulses, if you wanted to!

What I would do was to generate something like a real slow signal, like 100mS on/off pulse (PWM at 10Hz 50% duty cycle for instance) and then get the motor to run properly! Then once it is running I would try to speed it up!

There is in fact a limit to how fast your stepper can run! But not how slow.

- Brian

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting how the question was posed and where we've got to now.
Avr-gcc has a couple of delay functions that might prove handy. These are
_delay_us()
_delay_ms()

Google thse and you'll hit upon the manual describing the use of these. Don't give them a variable as the code will bloat. Read the instruction to avoid asking the same question that has been asked a thousand times before.

For a quick test, write something like this:

While (1)
{
set port bit
_delay_us(10);
Clear port bit
_delay_ms(100);
}

Now, you might want this to happen via an interrupt and you'll most likely want a variable speed and maybe keep track of the position. You'll need to find the maximum speed as this affects the rate at which you set the timer at. Lets say 1000 steps per second. Setup a timer in CTC mode to interrupt every 1ms. In the isr we add a speed value to a static variable. If we use unsigned integers, we test for whenever bit 15 of our static variable changes, if it does we output a pulse. This will give you a speed range of 1000/32768 pulses per second up to 1000 pps.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok I will use the above and report my findings :)

Thanks guys! Really helpful and useful forum :).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey Guys.

Just an update!
I have made some progress BUT its still not working as intended.
The motor usually ran really really choppy and made allot of noise when I pulsed it as fast as I could using Millis() on the arduino.
So then I decided to try a PWM.
Now a PWM on the arduino is really simple right.. AnalogWrite(1-255) and off it goes.

Problem now is even though it goes waaaay smoother and at a much faster rate it seems that no matter what number i insert into the AnalogWrite(x) brackets the speed doesnt seem to change at all! ??
I could use AnalogWrite(1)
or
AnalogWrite(100)
or
AnalogWrite(254)

ALL of them gives exactly the same motor speed.
Does anybody have any idea what this could be?

Thanks :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cartman wrote:
I could use AnalogWrite(1)
or
AnalogWrite(100)
or
AnalogWrite(254)

ALL of them gives exactly the same motor speed.
Does anybody have any idea what this could be?

A look at the data sheet shows that this is a stepper motor driver. You can't affect the speed of the motor by changing the duty cycle of a PWM signal driving it's 'pulse' input. You'll have to change the PWM frequency for that. You can't do that with analogWrite().

Have you made changes to the way PWM is configured? By default, on the Uno, PWM via analogWrite() is set to use a prescaler of 64, and 8-bit Phase Correct PWM mode. At 16 MHz, this yields a PWM frequency of 16000000/64/510 = 490 Hz. This is true for all PWM outputs using TIMER1 and TIMER2, namely Arduino pins 9, 10 (TIMER1), 3, and 11 (TIMER2). For PWM outputs using TIMER0 (pins 5 and 6), it's a bit different as TIMER0 is used for the timing functions millis(), micros(), andn delay(). It is configured for 8-bit Fast PWM, so the frequency is 16000000/64/256 = 976 Hz.

The frequency of the PWM is going to translate to the speed of your stepper motor. 490 Hz will correspond to 490 steps per second.

[edit]Ah. Stepper motor. Re-wrote response[/edit]

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Mon. May 13, 2013 - 08:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
You'll have to change the PWM frequency for that. You can't do that with analogWrite().

Yes that is indeed one of the reason I resorted to the naked atmel IC.
But can you change a PWMs frequency on the Go? Like can it be done while it is running?Because that would really be what I need :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cartman wrote:
Yes that is indeed one of the reason I resorted to the naked atmel IC.
But can you change a PWMs frequency on the Go? Like can it be done while it is running?Because that would really be what I need :)
Of course. I'd avoid analogWrite() altogether. Configure a timer from scratch. I might suggest TIMER1, as it will give you finer control with 16 bits. Something like:
#define STEPS_PER_REVOLUTION 200

void run_stepper(uint16_t rpm) {

  double freq;
  uint32_t cycles, resolution;
  uint8_t prescaler;
  uint8_t prescaler_bits;
  uint8_t top;

  // configure OC1A as an output
  pinMode(9, OUTPUT);
  
  // rpm == 0 means stop
  if (rpm == 0) {
  
    prescaler_bits = 0b000;
    top = 0;
    
  }
  // otherwise, select closest prescaler and TOP
  else {

    // double the PWM frequency, because we are using toggle mode for OC1A
    freq = ((double)STEPS_PER_REVOLUTION / 30) * rpm;
    
    // number of CPU cycles
    cycles = ((double)F_CPU  / freq) + 0.5;  /* with banker's rounding */

    // calculate ideal TIMER1 prescaler required for maximum resolution over
    // defined refresh rate
    prescaler = cycles / 0x10000;

    // always round up any fractional result (ensures resolution will fit prescaler)
    if (cycles % 0x10000)
      (prescaler)++;

    // select next highest available prescaler
    if (prescaler > 256) {
      prescaler = 1024;
      prescaler_bits = 0b101;
    }
    else if (prescaler > 64) {
      prescaler = 256;
      prescaler_bits = 0b100;
    }
    else if (prescaler > 8) {
      prescaler = 64;
      prescaler_bits = 0b011;
    }
    else if (prescaler > 1) {
      prescaler = 8;
      prescaler_bits = 0b010;
    }
    else {
      prescaler = 1;
      prescaler_bits = 0b001;
    }

    // compute TIMER1 resolution (with banker's rounding)
    resolution = ((((cycles * 2) / prescaler) + 1) / 2);

    // if refresh rate is beyond capabilities of TIMER1 (or has rounded beyond
    // full scale for selected prescaler), use closest possible
    if (resolution > 0x10000)
      top = 0xFFFF;
    else
      top = resolution - 1;
  
  }

  // mode 14, fast PWM, TOP = ICR1A, toggle OC1A on compare match
  TCCR1A = _BV(COM1A0) | _BV(WGM11);
  TCCR1B = _BV(WGM13) | _BV(WGM12) | prescaler_bits;
  OCR1A = top;

  // output
  DDRB = _BV(PORTB0) | _BV(PORTB1) | _BV(PORTB2);

}

Will drive your stepper from pin 9 on the Uno. At 16 MHz, with a 200-steps-per-revolution stepper motor, you should be able to get speeds between 0.036 rpm and 2.4 million rpm (well beyond what any stepper can do, obviously ;) )

Untested. UAYOR. Note that I have not handled the 'enable' input to your driver module.

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]