Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
- Committer:
- rakware
- Date:
- 2018-08-01
- Revision:
- 5:8965c2919afb
- Parent:
- 4:2235d6d01ca5
- Child:
- 6:c74fa5932b21
File content as of revision 5:8965c2919afb:
#include "mbed.h" //uses https://github.com/ARMmbed/mbed-os/
DigitalOut led(LED1); //board led, just for fun
Serial pc(USBTX, USBRX); // tx, rx pc control over usb
uint16_t gn = 0; //position to move to
uint16_t gp = 0; //current position
uint16_t temperature = 255; //hardcoded for now //TODO
bool is_moving, move = false;
uint16_t step_delay = 256;
//minimum motor speed that will get doubled 5 times to result maximum motor speed
//eg: for a value of 100 there will be 5 speeds as follows 100*1,100*2,100*4,100*8,100*16
//eg: for a value of 100 there will be 5 speeds as follows 100,200,400,800,1600
uint8_t min_motor_pps = 75;
char ml_in[256];
uint8_t idx = 0;
Thread led_thread, motor_thread;
void led_blink()
{
while (true) {
led = !led;
wait(1);
}
}
//motor control with MP6500 https://www.pololu.com/product/2968
//aproximate formula for motor current control pwm.pulsewidth% = (motor_rated_current_in_amps-2.2)/-2.079, so for our 330ma motor we use pw = (0.330-2.2)/-2.079
// https://www.pololu.com/product/2968#lightbox-picture0J8398;main-pictures , 1 kHz or greater, I2 set to low
//D2,D3,D4,D5,D6,D7,D8,D9 - DIR, STEP, SLP, I2, I1, MS2, MS1, EN
DigitalOut dir(D2);
DigitalOut step(D3);
DigitalOut slp(D4); //pull high to enable operation
DigitalOut i2(D5); //set low to enable pwm power control
PwmOut i1(D6); //MP6500 power limit control
DigitalOut ms2(D7);
DigitalOut ms1(D8); //set low for FULL or high for HALF, only use MS1 to be moonlite compliant ?
DigitalOut en(D9); //pulled low by the motor driver, default enables operation
float motor_max_amps = 0.33f;
float pw = (motor_max_amps-2.2f)/-2.079f;
void mp6500() //TODO enable/disable motor
{
dir = 0;
step = 0;
slp = 1;
i2 = 0;
i1.period(0.001f); //1kHz period
i1.write(pw);
ms2 = 0;
ms1 = 1;
en = 0;
}
void motor()
{
while (true) {
if(move) {
i1.write(pw); //set defined current motor while moving
is_moving = true;
if(gp > gn) {
dir = 0;
wait_us(1);
//__disable_irq(); // Disable Interrupts because serial irq makes motor move funky with indi_moonlite_focuser polling
//__enable_irq(); // Enable Interrupts
//led = !led;
step = !step;
wait_us(1); //mp6500
//led = !led;
step = !step;
wait_us(1);
//https://os.mbed.com/docs/v5.9/mbed-os-api-doxy/mbed__wait__api_8h_source.html use Thread::Wait()?
wait((step_delay/1.024)/min_motor_pps/250);
gp--;
} else if (gp < gn) {
dir = 1;
wait_us(1);
//led = !led;
step = !step;
wait_us(1);
//led = !led;
step = !step;
wait_us(1);
wait((step_delay/1.024)/min_motor_pps/250);
gp++;
} else {
step = dir = 0;
wait_us(1);
i1.write(1f); //set minimum controller power while holding, keeps motor cool and still provides a nice holding torque, ~120ma
is_moving = false;
move = false;
}
}
}
}
//http://indilib.org/media/kunena/attachments/1/HighResSteppermotor107.pdf
void read_serial()
{
while(pc.readable()) {
char c = pc.getc();
switch (c) {
case '#':
switch (ml_in[0]) {
case 'C': //N/A Initiate a temperature conversion; the conversion process takes a maximum of 750 milliseconds. The value returned by the :GT# command will not be valid until the conversion process completes.
break; //TODO
case 'F':
switch (ml_in[1]) {
case 'G': //N/A Go to the new position as set by the ":SNYYYY#" command.
move = true; //runs motor();
break;
case 'Q': //N/A Immediately stop any focus motor movement.
move = false;
break;
default:
break;
}
break;
case 'G':
switch (ml_in[1]) {
case 'B': // Get the backlight value
pc.printf("00#");
break;
case 'C': //XX# Returns the temperature coefficient where XX is a two-digit signed (2’s complement) hex number.
pc.printf("02#");
break;
case 'D': //XX# Returns the current stepping delay where XX is a two-digit unsigned hex number. Valid values 02, 04, 08, 10, 20 -> stepping delay 250, 125, 63, 32, 16 pps
pc.printf("%02X#", 512 / step_delay); //TODO? we sleep for step_delay*step_delay_multiplier microseconds between steps
break;
case 'H': //00# OR FF# Returns "FF#" if the focus motor is half-stepped otherwise return "00#"
//pc.printf("00#"); //TODO
pc.printf("%02X#", ms1 * 255);
break;
case 'I': //00# OR 01# Returns "00#" if the focus motor is not moving, otherwise return "01#"
pc.printf("%02X#", is_moving);
break;
case 'N': //YYYY# Returns the new position previously set by a ":SNYYYY#" command where YYYY is a four-digit unsigned hex number
pc.printf("%04X#", gn); //TODO use this to move the motor
break;
case 'P': //YYYY# Returns the current position where YYYY is a four-digit unsigned hex number.
pc.printf("%04X#", gp); //TODO update gp with actual motor data
break;
case 'T': //YYYY# Returns the current temperature where YYYY is a four-digit signed (2’s complement) hex number.
pc.printf("%04X#", temperature * 2); //indi_moonlite_focuser returns the temp/2, dunno why, dont care
//pc.printf("0019#"); //should be 25c but is 12.5c in indi_moonlite control panel
break;
case 'V': //DD# Get the version of the firmware as a two-digit decimal number where the first digit is the major version number, and the second digit is the minor version number.
pc.printf("01#");
break;
default:
break;
}
break;
case 'S':
switch(ml_in[1]) {
case 'C': //N/A Set the new temperature coefficient where XX is a two-digit, signed (2’s complement) hex number.
break; //TODO
case 'D': //N/A Set the new stepping delay where XX is a two-digit, unsigned hex number. Valid values to send are 02, 04, 08, 10 and 20, which correspond to a stepping delay of 250, 125, 63, 32 and 16 steps per second respectively.
step_delay = 512 / strtol(ml_in + 2, NULL, 16);
break;
case 'F': //N/A Set full-step mode.
ms1 = 0;
break;
case 'H': //N/A Set half-step mode.
ms1 = 1;
break;
case 'N': //N/A Set the new position where YYYY is a four-digit unsigned hex number.
gn = strtol(ml_in + 2, NULL, 16); //read ml_in, discard 2 chars, convert to long, set gn
break;
case 'P': //Set the current position where YYYY is a four-digit unsigned hex number.
gp = strtol(ml_in + 2, NULL, 16);
break;
default:
break;
}
break;
case '+': //N/A Activate temperature compensation focusing.
break; //TODO
case '-': //N/A Disable temperature compensation focusing.
break; //TODO
case 'P':
break;
// case ':POXX#': //N/A Temperature calibration offset, XX is a two-digit signed hex number, in half degree increments. Example 1: :PO02# offset of +1°C Example 2: :POFB# offset of -2.5°
// break; //TODO
default:
break;
}
break;
case ':':
idx=0;
memset(ml_in, 0, 8);
break;
default:
ml_in[idx++] = c;
idx %= 8;
break;
}
}
}
int main()
{
mp6500();
//led_thread.start(led_blink);
pc.attach(read_serial, Serial::RxIrq);
motor_thread.start(motor);
while(true) {
Thread::wait(100);
//read_serial();
}
}