# coding...

A project log for drillPresseur - Drill-Press with Force-Feedback

OK, most drill-presses have "force-feedback" in the normal sense... so this is a bit ridiculous.

Eric Hertz 12/01/2016 at 17:410 Comments

I have no idea whether this'll fit... but I think I've done the biggest portions, thus-far (int32 math!), and we're fitting in 542Bytes...

```#include <avr/io.h>
#include <inttypes.h>

typedef struct motorThing
{
int32_t desiredPos;
int32_t actualPos;
uint8_t pwm;   //Assuming PWM=128 ==> 0 power
//PWM=0 ==> Full-Reverse
//PWM=255 ==> Full-Forward
uint8_t kP; //Ideally, this'd be constant...
} motor_t;

motor_t motorA = { 0, 0, 0, 1};
motor_t motorB = { 0, 0, 0, 1};

uint8_t pwmify(motor_t *motor)
{
//Assuming "power" is > 0 when moving toward desiredPos>0 from 0...
int32_t power = (motor->desiredPos - motor->actualPos) * motor->kP;

//Using whatever-it's-called PWM, where 0 *power* = 128 *pwm*:
if(power > 127)
return 255;
else if(power < -127)
return 0;
else // -127 < power < 127
return power + 127;
}

#define posRatioA   1
#define posRatioB   1

#define HEART_pin    1
#define HEART_PORT   PORTB
#define HEART_PIN    PINB
#define HEART_DDR    DDRB

int main(void)
{

//TODO:
// Initialize the timer(s) for PWM output:

//Indicate the loop-rate via an LED...
// (Use a 'scope to check it)
#warning "VERIFY! 1 = output?"
DDRB |= 1<<(HEART_pin);

while(1)
{
//As long as this LED toggles at a rate faster than our encoders can
//increment, we don't need to use interrupts to handle the encoders
#warning "VERIFY!"
if(HEART_PIN & (1<<HEART_pin))
HEART_PORT &= ~(1<<HEART_pin);
else
HEART_PORT |= (1<<HEART_pin);

//TODO:
// Read the Encoders!

//Tie the two motors together...
motorA.desiredPos = (motorB.actualPos * posRatioA) / posRatioB;
motorB.desiredPos = (motorA.actualPos * posRatioB) / posRatioA;

//Determine the new PWM values for each motor
motorA.pwm = pwmify(&motorA);
motorB.pwm = pwmify(&motorB);

//TODO:
// Output the PWM values to the OCR's

}
}
```

Seems doable....

------------

HOWEVER:

The optimizer's pretty durn smart...

And it might just recognize that the math here doesn't result in any *changes*... Since... The encoders aren't yet implemented. So, it's *plausible* that once this thing gets some encoders-involved, things might increase quite a bit. A *reasonable* test would be to create a function to "pretend" to set encoder-values, and set those variables "volatile"... but of course, I'm not capable of thinking in that realm, right now...

----------

It (mah-brain) is, however, capable of adding "volatile" to "actualPos" in the struct...

And the result is *exactly* the same, size-wise...

Which... I dunno whether to be happy about, or confused about.

On the one hand, that might just well mean that I don't have to worry about code-size increasing dramatically when I add the encoder-handling...

On the other hand... if the optimizer's not capable of recognizing that actualPos doesn't change... (from 0), then ... am not nearly as impressed (maybe even somewhat "disillusioned"?) by the optimizer's abilities.

On the third hand... if the optimizer *completely disregards* the volatile statement, in this case, it might mean that it's recognizing that the value *still* isn't changed, despite being marked volatile, which might mean that I've got *a lot* to worry about, once I introduce the encoder-handler...

Oy!

-----------

Or there might be a fourth-hand, which I can't quite comprehend right now...

THIS results in 562 Bytes... that's only 20 more than previous... and This should Guarantee that "actualPos" isn't being presumed to be any particular value, which should, therefore, assume that ... no, I don't *call* the function. WHOOPS

-------------

OK...

HERE WE GO...

I think this be right.

Now we're at 610 Bytes.

```#include <avr/io.h>
#include <stdint.h>

typedef struct motorThing
{
int32_t desiredPos;
volatile int32_t actualPos;
uint8_t pwm;   //Assuming PWM=128 ==> 0 power
//PWM=0 ==> Full-Reverse
//PWM=255 ==> Full-Forward
uint8_t kP; //Ideally, this'd be constant...
} motor_t;

motor_t motorA = { 0, 0, 0, 1};
motor_t motorB = { 0, 0, 0, 1};

uint8_t pwmify(motor_t *motor)
{
//Assuming "power" is > 0 when moving toward desiredPos>0 from 0...
int32_t power = (motor->desiredPos - motor->actualPos) * motor->kP;

//Using whatever-it's-called PWM, where 0 *power* = 128 *pwm*:
if(power > 127)
return 255;
else if(power < -127)
return 0;
else // -127 < power < 127
return power + 127;
}

#define posRatioA   1
#define posRatioB   1

#define HEART_pin    1
#define HEART_PORT   PORTB
#define HEART_PIN    PINB
#define HEART_DDR    DDRB

void updateActualPos(motor_t *motor)
{
#warning "THIS IS A MAJOR HACK!"
//Just trying to insert *something* that the optimizer shouldn't
//optimize-out... THIS IS NOT VALID DATA!!!!
motor->actualPos = PINA;
}

int main(void)
{
//TODO:
// Initialize the timer(s) for PWM output:

//Indicate the loop-rate via an LED...
// (Use a 'scope to check it)
#warning "VERIFY! 1 = output?"
DDRB |= 1<<(HEART_pin);

while(1)
{
//As long as this LED toggles at a rate faster than our encoders can
//increment, we don't need to use interrupts to handle the encoders
#warning "VERIFY!"
if(HEART_PIN & (1<<HEART_pin))
HEART_PORT &= ~(1<<HEART_pin);
else
HEART_PORT |= (1<<HEART_pin);

//Pretend to read the encoders
updateActualPos(&motorA);
updateActualPos(&motorB);

//Tie the two motors together...
motorA.desiredPos = (motorB.actualPos * posRatioA) / posRatioB;
motorB.desiredPos = (motorA.actualPos * posRatioB) / posRatioA;

//Determine the new PWM values for each motor
motorA.pwm = pwmify(&motorA);
motorB.pwm = pwmify(&motorB);

//TODO:
// Output the PWM values to the OCR's

}
}
```