LudoMTR (Part 5)

Part 123456

Adjusting the rotor speed requires that the potentiometer is very slowly and constantly move CW or CCW. Failing to do so results in slippery of the magnetic field versus the rotor. In other words, the rotor does not have the time to change speed and looses its synchronisation.

Version 2 of LudoMTR includes an intertial control of the acceleration/deceleration of the rotor. If the speed setting differs from the current speed, a constant fraction of the current speed (expressed in ppm) is added/subbtracted to the current speed.

Here comes the revised code. The skecth contains number of refinements, such as direct expression of speed which is then converted in intervals duration, add of a synchronisation signal.

/*

	Copyright (C) 2012 Didier Longueville

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#define maskD 0xFC /* Port D digital pins 2 to 7 */
#define maskB 0x3F /* Port B  digital pins 8 to 13 */

#define CUR_REVERSE -1 /* Current flows from port D to port B */
#define CUR_NONE 0
#define CUR_FORWARD 1 /* Current flows from port B to port D */

#define steadyStateLedPin 4
#define synchPin 3
#define speedMax 1250
#define speedMin 250

long lastCycleTime = micros();
long targetCycleInterval; 
long currentCycleInterval; 
char currentDirection = CUR_FORWARD; /* Default current direction */
int rateOfChange = 500; /* ppm */

void setup()
{
	/* Set ports */
	DDRB |= (maskB); /* Rotor Pole B */
	DDRD |= (maskD); /* Rotor Pole D */
	DDRC |= (1 << steadyStateLedPin); /* Set steady state led pin as an output pin*/
	DDRC |= (1 << synchPin); /* Set synchronization pin as an output pin*/
	setCurrent(CUR_NONE);
	setSpeed();
	currentCycleInterval = targetCycleInterval;
	/* For diag purpose */
	Serial.begin(115200);
}

void loop()
{
	PORTC ^= (1 << synchPin);
	setSpeed();
	if (currentCycleInterval == targetCycleInterval) {
		PORTC |= (1 << steadyStateLedPin);	/* Turn on steady state led */
	}
	else {
		PORTC &= ~(1 << steadyStateLedPin);	/* Turn off steady state led */
		long stepSize = (currentCycleInterval * rateOfChange) / 1000000UL;
		if (currentCycleInterval < targetCycleInterval) {
			currentCycleInterval += stepSize;
			if (currentCycleInterval > targetCycleInterval) currentCycleInterval = targetCycleInterval;
		}
		else if (currentCycleInterval > targetCycleInterval) {
			currentCycleInterval -= stepSize;
			if (currentCycleInterval < targetCycleInterval) currentCycleInterval = targetCycleInterval;
		}
	}
	/* Set next cycle time */
	long nextCycleTime = (lastCycleTime + currentCycleInterval);
	/* Wait next pulse */
	long now;
	do
		now = micros();
	while(now < nextCycleTime);
	/* Set current flow */
	setCurrent(currentDirection);
	/* Flip current direction for next pulse */
	currentDirection *= -1; 
	/* Record last pulse time */
	lastCycleTime = now;
	/* Set pulse stop time */
	long pulseStopTime = (lastCycleTime + long((currentCycleInterval << 1) / 3));
	/* Wait until pulse duration has elapsed */
	do
		now = micros();
	while(now < pulseStopTime);
	/* Cancel current */
	setCurrent(CUR_NONE);
};

void setSpeed(void)
{
	targetCycleInterval = 30000000UL / map(analogRead(0),0, 1023, speedMin, speedMax);
};

void setCurrent(char value)
/* Set current flow between PORTB and PORTD pins */
{
  switch(value) {
	case CUR_REVERSE:
		PORTD |= (maskD);		
		break;
	case CUR_NONE:
		PORTB &= ~(maskB);	
		PORTD &= ~(maskD);	
		break;
	case CUR_FORWARD:
		PORTB |= (maskB);			
		break;
	}
};

Few additional improvements have been brought to the code. At start, the speed setting and the current speed are equal and relate to the potentiometer position.

 

Next post on same subject

Leave a Reply

You must be logged in to post a comment.