DUE, steppermotor peristaltic-pump, oled-screen, rotary encoder

Hi all,

The board I am using is Due, and the stepper motor driver is TB6600.
Main question is how to run the stepper motor pump smoothly at any given rpm? The application does not require absolute step information, but just rpm that is consistent, to give a stable flow.

I can easily run the pump with just bit banging. The problem is that I should be able to run the GUI on the screen at the same time, without interrupting the peristaltic pump.

First option that came to my mind, is to just use hardware PWM with 50% duty-cycle and vary the frequency to achieve different rpms. This turned out to be a bit difficult, and to my understanding, it will change the frequency on more that one pwm pin and scaling the timer would affect system wide.

Second option would be to use timer interrupts, to change the the PUL-line to HIGH or LOW on specified intervals to achieve different rpm. I have no clue on exactly how accurate this would be.

Last option, would be to add a circuit which would give a frequency of 1Hz to 1KHz with an input of 0-3.3v. I am not so adept in designing circuits, so this option seems a bit difficult too, but not unfeasible if really needs to be done this way.

If you consider the first option, the PWM peripheral has registers to update frequency and duty cycle on the fly, respectively PWM_CPRDUPD and PWM_CDTYUPD. They are to be used in loop() once a PWM channel has been enabled in setup(). The update is triggered at the next PWM period.

Hi,
Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Also post the specs/data of your stepper and how you are powering the project.

Thanks.. Tom.. :slight_smile:

Hi,
You need to have a look at AccelStepper Library, I'm not sure if it will run on the DUE, but it can do all the stepping and speed control.

Google controlling a TB6600 stepper driver with arduino DUE

Tom... :slight_smile:

TomGeorge:
Hi,
You need to have a look at AccelStepper Library, I'm not sure if it will run on the DUE, but it can do all the stepping and speed control.

Google controlling a TB6600 stepper driver with arduino DUE

Tom... :slight_smile:

Hi,

I skimmed the code, and it is basically just bit banging from the main loop and adjusting the speed with what is the micros() from loop in order not to delay or block the main loop. Could work of course, so lets say this is option 2.2. So instead of timer interrupts, let's see what the delay is and work with that. This, just means, that the GUI-code should not for any reason cause unforeseen blocks for main loop.

These links may be of interest.

Stepper Motor Basics
Simple Stepper Code

The code in the examples does not need any library.

...R

Talonmies84:
The board I am using is Due, and the stepper motor driver is TB6600.
Main question is how to run the stepper motor pump smoothly at any given rpm?

You can setup one of the timers in the Due to output a waveform which will then run independently (it's all in hardware)

This example will output a 50uS pulse at a given frequency on pin 5 which you can drive the TB6600's pulse input, the code in loop() just increments the frequency every 0.1 second from 150Hz to 1kHz

#include <Arduino.h>
//
// *** Arduino Due ONLY ***
// Example of setting up a timer to generate an output waveform
//
#define TC2_CH0_ID  (33)  // peripheral ID (TC instance 6)
#define PULSE_50uS  (33)  // counter value for 50uS pulse

//-----------------------------------
// Set period of waveform output
// - period is the counter value for the waveform period 
// - pulse is the length of the TIOA6 high pulse
// NOTE: period must be greater than pulse.
//
// Values are in units of 1.52uS
//
void SetPeriod( uint32_t period, uint32_t pulse )
{
  REG_TC2_CCR0= TC_CCR_CLKDIS;   // clock disable
  REG_TC2_RA0= period - pulse;
  REG_TC2_RC0= period;
  REG_TC2_CCR0= TC_CCR_CLKEN;   // clock enable
  REG_TC2_CCR0= TC_CCR_SWTRG;   // trigger
}

//-----------------------------------
// Set frequency from 1Hz to 10000Hz
// - output is a 50uS pulse at the given frequency 
//
void SetFrequency( uint32_t Hz )
{
  if( (Hz > 0) && (Hz <= 10000) ){
      SetPeriod( 656250u / Hz, PULSE_50uS ); 
  }
}


//-----------------------------------
// Setup TimerCounter 2, channel 0 (TC instance 6)
// for waveform output, RA compare toggles TIOA6
// TIOA6 is output on PC 25, peripheral B, Arduino Due digital pin 5
// Timer counts at mclk/128 = 84MHz / 128 = 656,250Hz
//
void SetupT2C0_Waveform()
{
  // Power Management Controller PMC...
  // TC2 peripheral ID = TC2_CH0_ID
  // - enable peripheral clock = MCK/4
  // *NOTE* PMC_PCER0 enables peripheral ID's 2..31
  //        PMC_PCER1 enables peripheral ID's 32..44
  //
  REG_PMC_PCDR1 = 0x1u << (TC2_CH0_ID - 32); // Disable clock
  //              DIV=2        CMD=Write     PID
  REG_PMC_PCR= (0x2u << 16) | (0x1u << 12) | TC2_CH0_ID;
  REG_PMC_PCER1 = 0x1u << (TC2_CH0_ID - 32); // Enable clock

  // Using Timer Counter 2, channel 0  (instance T6)
  // - waveform mode, clock = mclk/128 = 650kHz
  // - RA sets TIOA6, RC reloads count and cleats TIOA6
  //
  REG_TC2_CMR0=  TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4 
               | TC_CMR_ACPA_SET | TC_CMR_ACPC_CLEAR | TC_CMR_ASWTRG_CLEAR;

  SetPeriod( 0x100, 0x10 );

  // TIOA6 - output on PC 25, peripheral B, digital pin 5
  pinMode( 5, OUTPUT );
  REG_PIOC_PDR = 0x1u << 25;   // enable peripheral control
  REG_PIOC_ABSR |= 0x1u << 25; // peripheral B select
}


void setup() {

  Serial.begin(9600);
  Serial.println("Example Waveform output on Arduino Due\n");

  SetupT2C0_Waveform();
}

void loop() {
  static uint16_t freq= 150;

  Serial.print("freq= "); Serial.println(freq); 
  SetFrequency( freq );
  delay(100);

  freq += 10;
  if( freq > 1000 )
    freq= 150; 
}

The code runs an Arduino Due ONLY since it pokes specific timer registers.

Caution
I usually write stuff for SAM-series devices by directly handling the hardware (like above), so I have no idea what compatibility issues there may be if you are using other libraries at the same time which might manipulate the timers.

Yours,
TonyWilk

Hi again...
Happened to leave the example code from my previous post running and noticed the 'scope this morning and realised:
a. That's almost what I want for something else I'm working on
b. it glitches when writing new timer values

so... Mk.II (attached)

This version runs the timer at full speed to allow generation of any frequency from 20MHz down to sub-Hz.

The functions to SetPeriod(), SetPulsePeriod() and SetSquarewave() now adjust the timer synchronously (i.e. the current period is allowed to elapse before setting new values).

Also added StopWaveform(), which might be handy if you are driving a stepper with it.

Yours,
TonyWilk

TimerPulse2.ino (6.5 KB)

TonyWilk:
Hi again...
Happened to leave the example code from my previous post running and noticed the 'scope this morning and realised:
a. That's almost what I want for something else I'm working on
b. it glitches when writing new timer values

so... Mk.II (attached)

This version runs the timer at full speed to allow generation of any frequency from 20MHz down to sub-Hz.

The functions to SetPeriod(), SetPulsePeriod() and SetSquarewave() now adjust the timer synchronously (i.e. the current period is allowed to elapse before setting new values).

Also added StopWaveform(), which might be handy if you are driving a stepper with it.

Yours,
TonyWilk

Thank you very many. This was exactly what I searched for!