Show Posts
Pages: [1] 2
1  Community / Exhibition / Gallery / Arduino stepper code tutorial for time lapse control unit on: April 04, 2014, 05:04:45 pm
Hey gang!

Just thought I'd share in case this is useful for anyone.  I've spent the last two weeks putting together a tutorial which guides you through how to code a time lapse control engine on an Arduino.  I start off real slow/basic so if you are new to Arduino or not very familiar with it, this is a great starting place.  It's divided into 5 parts and in the end I show how to code a system that makes use of a joystick, LCD, a button several libraries and a menu system to create a nice SMS style time lapse controller.  Enjoy!

Find the first part here: http://www.photocs.net/arduino-stepper-code-basic
2  Using Arduino / Programming Questions / Re: i2c speeds, buadrates, and bottlenecks - double check my thinking? on: January 29, 2014, 10:36:38 am
Thanks Rob!  Your reasoning makes sense and in all actually I think we came up with the same rough values.  The only place I went wrong was the last step:

5 - if i'm still correct, does that mean i can send data from the master Arduino to the PC at a baud rate of 16.8 * 8 = ~135baud without causing a bottleneck?

I dropped the 'kilo' on that calculation; the correct value should have been 135kbps instead of 135bps

I think I'll have to look into feeding the i2c feed directly into the PC & sending a smaller byte package across.  Thanks for the help!
3  Using Arduino / Programming Questions / i2c speeds, buadrates, and bottlenecks - double check my thinking? on: January 28, 2014, 11:47:50 pm
hey everyone!

I'm working on a project that will have several (on the order of 12) Arduino Mini Pro (5V/16MHz) boards measuring orientation data through a 6DOF IMU chip and all connected through a i2c bus; I plan on having a master Arduino (such as a teensy) be the one that collects all the i2c data and sends it through serial to a computer.  I'm trying to run the numbers to make sure I'm not running into any bottlenecks, and I was hoping someone could double check my logic.  Here goes:

1 - the orientation IMU samples at 100Hz and spits out a 42-byte buffer with the info for each sample ( see lines 120-128 of https://github.com/jrowberg/i2cdevlib/blob/master/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h)
2 - my mini pro processes this 42-byte buffer and sends it down the i2c bus as a 14-byte packet - here i'm assuming it can do it as fast as it's receiving data: 100Hz (so does it make sense that it's sending data down at 14 * 100 = 1.4 kbyte/s?)
3 - my i2c bus is running at an ~ideal 400 kbit/s = 50 kbyte/s
4 - so if I have 12 boards running the IMUs does that mean I'm sending 12 * 1.4 = 16.8 kbyte/s down the bus?
5 - if i'm still correct, does that mean i can send data from the master Arduino to the PC at a baud rate of 16.8 * 8 = ~135baud without causing a bottleneck?

Granted, all of these are ideal conditions, but I'm wondering if the reasoning and calculations are right.  Thanks for the help everyone!
4  Products / Arduino Due / nanos() [time elapsed since program start in nanoseconds]? on: November 26, 2013, 06:46:54 pm
hi everyone!

In my current application I'd like to be able to have access to timing in the 10 to 100 ns range.  So I started digging around in the micros() source code and came up with the following:

Code:
uint32_t nanos( void )
{
    uint32_t ticks ;
    uint32_t count ;

    SysTick->CTRL;
    do {
        ticks = SysTick->VAL;
    } while (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk);

    // GetTickCount() is millis()
    uint32_t load= (SysTick->LOAD + 1 - ticks);
    uint32_t milliS = GetTickCount() * 1000000;
    uint32_t microS =  load/ (SystemCoreClock/1000000) * 1000;
    uint32_t nanoS = load/ (SystemCoreClock/10000000); // these are actually 100s of nanoseconds; 84MHz  = 11.9ns
   
    //Serial.print(milliS); Serial.print(" "); Serial.print(microS); Serial.print(" "); Serial.println(nanoS);
   
    return milliS + microS + nanoS;

}

It's exactly the micros() source code except that on the return I changed the divisions by 1000.  Could someone please comment on whether this is the right approach?

On a side note: isn't division notoriously slow on the Due, so isn't there a better way to optimize this code for performance?
5  Products / Arduino Due / interrupt for multiple stepper motors - optimized approach on: October 13, 2013, 01:09:15 pm
Hi everyone in the fellow arduino community!   smiley-mr-green

I was hoping i get could some thoughts/improvements on the way I'm approaching this code.  For the last year or so, I've been working on a project which involves being able to control up to 5 stepper motors in real time.  Each of the stepper motors require a digital pin to be toggled high/low at upwards of about 100kHz.  Given the fact this is is relatively fast (max interrupt speeds for a single ISR I've ready about are 1MHz on the Due) and that the timing of the motors is time sensitive, I want to make sure I'm approaching things in an optimized way.

I'm about to take another fresh go at the code and am thinking of the following structure; for each motor we are doing two time specific things:
1) toggling the step pin HIGH/LOW, the frequency of which is changed based on the stepper speed we want -- dictates as velocity.
2) adjusting the frequency with which we toggle the step pin HIGH/LOW; this is done at equal intervals -- dictates as acceleration.

point 1) is taken care of as follows:
- I've written up my own little library (named from here on as Engine) that keeps track of information for each declared motor.
- using the very excellent DueTimer library I setup an ISR that calls a step() function in my library, the step() function being simply defined along the lines of:
Code:
void Engine::step() {
   digitalWriteDirect(_stepPin, toggle = !toggle); // fast write to our step pin, alternates between HIGH/LOW
}

where digitalWriteDirect is defined as:
Code:
inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

This gives me a nice way of stepping motors at my required frequencies; however, in order to change the speed of motors, I have to adjust the frequency with which the step() function is called.



point 2) is handled as follows:
at this point, we've already used upwards of 5 timers (1 for each motor) which leaves us with only 4 left (correct me if I'm wrong). So we will have to do things the manual way by defining an accelerate function within my Engine library which adjusts speed and gets checked all the time (here is where we start slowing down); we'll need to accelerate for each motor (M) with something that looks like this:
Code:
void loop() {
   M1.accelerate();
   M2.accelerate();
   M3.accelerate();
   M4.accelerate();
   M5.accelerate();
}

with accelerate() being pseudo defined as something like:
Code:
void Engine::accelerate() {

   time = micros();

   if (time >= previousTime + _updateInterval) { // only update speeds after equal time intervals (_updateInterval) have passed: manual implementation of ISR

      given some condition, adjust our ISR call frequency for step(); // adjust our stepper speed
      update the proper ISR timer registry // update our ISR frequency which adjusts our stepping speed
      previousTime = time;

   }

}


here is where your smart brains come in; does anyone see an alternate approach?  weakness to my approach?  where can i speed things up?  would you do anything differently?  thanks everyone ahead of time!
6  Products / Arduino Due / Re: faster micros()? on: September 11, 2013, 09:55:07 pm
I do not recommend inlining micros(), because I coded it for robustness rather than speed. Inlining it will not gain you much.

Instead, if you are guaranteed that you will always be measuring strictly less than a millisecond, you can read the SysTick counter directly. The counter counts down from 83999 to 0 with each clock tick. You use it a bit like micros(), except that you have to handle the wraparound explicitly, and because it counts down the subtraction is the other way around. You could divide the result by 84 to get microseconds, but if you are after a specific delay would be better to multiply the delay you require by 84 to get it in clock ticks.


Thanks for the advice stimmer; that gave me a lot to think about.

Taking your cues; I've written something like this:
Code:
time = GetTickCount() * 1000 + (84000 - SysTick->VAL) / 84;
in order to get elapsed time instead of using micros().

Now, I understand it's very close to the code for micros(), but it's slimmed down. 

I'm hesitant on whether this offers any speed savings though; doing a naive print statement at 115200baud to check times, shows the same time required between both ways of checking time.  i wonder if this shouldn't be check with a scope though.  thoughts?
7  Products / Arduino Due / faster micros()? on: September 09, 2013, 06:01:58 pm
hi everyone,

i've got some code running a stepper motor (throwing a pin HIGH/LOW at equal intervals) and I'm using micros() to check times.  I'm concerned about optimized code and was wondering if there is a faster way to access a timer counter than just micros()?  I know there is an timer interrupt library floating around out there; but I wonder if it offers any speed increases?

I''m currently doing something like this:

Code:
setup() {
delayTime = 100; // time to wait (in microseconds)
}

loop() {
   time = micros();

   if (time >= previousTime + delayTime) {
      do something because our proper wait interval has passed;
      previousTime = time;
   }
}

it should also be noted; that in order to implement acceleration; the time delayTime will vary.  so i'm not certain if interrupts are the way to go...
8  Products / Arduino Due / Re: Timer Interrupts on Due on: August 27, 2013, 02:16:50 pm
this is a great thread, lots of good info here.  one related question, is it possible to use these timers to simply get elapsed time since program start?  i mean, is there a hardware implementation of micros()?
9  Products / Arduino Due / optimize code for stepping stepper motor on: August 27, 2013, 12:01:59 pm
hi everyone.  I was hoping you all could help me in optimizing some stepper code (and learn something new!).  the advantage of optimizing it a bit further is that i can potentially run more steppers at the same time.  since upgrading to the due, i'm not sure of how to fully optimize.  here is what i'm working with:

Code:
// function responsible for stepping (throwing step pin HIGH/LOW)
void Engine::step(void) {
   
  unsigned long _time = micros(); // i'm guessing this could be optimized, but how?
 
  // handles the case of time overflow, which occurs at about 70 minutes for micros;
  // so if _time overflows (goes back to 0) and our last step time is huge, let's reset it
  if (_time < _lastStepTime) {
    _lastStepTime = 0;
  }
 
  // responsible for stepping high
  if (_time >= _lastStepTime + _currentSpeed && !_stepCycle) { // only step HIGH after _currentSpeed has passed
    if (_stepActive) {
      digitalWriteDirect(_stepPin, HIGH); // step HIGH
    }
    _stepCycle = true;
    _lastStepTime = _time;

    // increment our absolute position based on direction traveled
    if (_dir) {
      _absPos++;
    } else {
      _absPos--;
    }
  }
 
  // responsible for stepping low
  if (_time >= _lastStepTime + _lowStepWait && _stepCycle) { // we can step LOW after a short period and if we have already stepped HIGH
    if (_stepActive) {
      digitalWriteDirect(_stepPin, LOW); // step LOW
    }
    _stepCycle = false;
    _lastStepTime = _time;
  }
}

i'm aware that on the Uno there is a much faster way of checking micros() directly from the registry through TCNT1; i wonder if we can do this for the Due? 

how about any further optimization?  i'm guessing there isn't any other blaring change.. any help is much appreciated!
10  Products / Arduino Due / SPI TFT library for due on: July 13, 2013, 08:32:09 am
hey everyone!

I bought two SPI TFT LCDs from China off ebay; one with the ST7735R driver, the other with the ILI9341 driver

I'm wondering if anyone has had any luck with the SPI versions of TFT LCDs on their DUE; it looks like plenty of people got the non-SPI versions working...  

I know Adafruit has a nice SPI TFT library for the ST7735, but it needs to be ported over to the DUE.

Also, seeed has a library that works with the ILI9341, but it also needs to be ported over.  Actually, I was able to port it quite easily (changed port declarations) but it doesn't seem to be working on my LCD or perhaps I'm doing something wrong.

I also found an ATMEL software framework for the ILI9341 but I can't tell what this is or if it'll work with the DUE, thoughts?

So, anyone have any luck with the SPI TFT LCDs?  Any pointers or libraries I should check out?  Thanks for the help!

EDIT: looks like someone ported over the adafruit library; however, after hooking things up I'm still only getting a solid white screen.  I wonder if the ST7735R is that much different than the ST7735...
11  Products / Arduino Due / Re: help with Serial setup on: April 24, 2013, 04:43:39 pm
do you have to use low level code or can you use the Arduino serial library to set the comms, poll the buffer, then get any traffic?

no, i don't have to use lower level code, i just need to take the following code snippet and port it to a DUE:
Code:
   if (*txBufPtr)
    {
      if ((UCSRA) & (1 << UDRE))
      {
        UDR = *txBufPtr++;
  
        // we are done with this msg, get the next one
        if (!*txBufPtr)
          nextMessage();
      }
    }
12  Products / Arduino Due / help with Serial setup on: April 01, 2013, 03:30:22 pm
Hi everyone,

I'm modifying a piece of code written for the UNO to run on the DUE.  The code basically listens for commands over serial from a PC and then acts on those commands.  I've got everything ported over except for the lines dealing with serial communication.  The specific part I have yet to port over looks very similar to an example detailed in the datasheet for the ATmega328P (Arduino UNO); the code from the datasheed (p.184) looks like:
Code:
void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) )
;
/* Put data into buffer, sends the data */
UDR = data;
}
From datasheet -- The function simply waits for the transmit buffer to be empty by checking the UDRE Flag, before loading it with new data to be transmitted.

on the DUE side I've written it up as:
Code:
void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( USART1->US_CSR & US_CSR_TXRDY))
;
/* Put data into buffer, sends the data */
USART1->US_THR = data;
}

However, the function isn't working properly - it always stays in the while loop after a message is sent over serial from PC.  I was hoping someone could help me out with this since I'm not real familiar with this lower level stuff.  I'm not sure if/how I have to setup the serial connection by enabling transmission as well as the baud rate.  For now I've got things setup like:
Code:
// Reset and disable receiver & transmitter
USART1->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS;
  
// Configure mode
USART1->US_MR = 0;
  
// Enable transmitter
USART1->US_CR = US_CR_TXEN;

Can anyone help or offer pointers as to what I may be doing wrong?  Thanks!
13  Using Arduino / Programming Questions / Re: understanding timer interrupts on: April 01, 2013, 08:54:35 am
I assume that the overflow ISR is doing something with toggling pins based upon the comments.

Yep, you assumed correctly. The code is used to drive a stepper motor which needs an alternating HIGH/LOW sequence of pin actuation.

In the original the ISR didn't do anything at all because it was misnamed:

Code:
ISR(TIMERx_OVF_vect)

Yep, it was misnamed, must have happened while I was doing some reading on TIMERx, the correct version should be:
Code:
ISR(TIMER1_OVF_vect)
14  Using Arduino / Programming Questions / Re: understanding timer interrupts on: March 31, 2013, 06:05:29 pm
Quote
Is it correct to assume that the timer overflows every ...

Yes, plus 1.

If the number happens to be 50, it will count 51 times because it includes zero.

Quote
So, using the Due timer/interrupt library I could simply do: ...

I haven't used the Due yet, but in principle that looks OK.

Hi Nick!

thanks for the speedy replies and help, I'll get to some testing this week and post back if I'm having any difficulty!
15  Products / Arduino Due / porting serial commands on: March 31, 2013, 06:02:58 pm
hey ya'll!

i'm trying to port over some code from an Uno to the Due and I've nearly got everything covered except for the part that deals with serial communication.  i've looked through the Atmel data sheet but i'm not quite sure about the equivalent data registry and controls.

the original code makes reference to the following:
Code:
UCSRA
UDRE
UDR

and from reading in the datasheet, the nearest equivalent i can find to them (respectively) are:
Code:
US_CR
ENDRX
US_RHR

could someone please confirm/correct this?  thank you!
Pages: [1] 2