Radu Radoveneanu / Mbed OS moonlitemockup
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h" //uses https://github.com/ARMmbed/mbed-os/
00002 
00003 DigitalOut led(LED1); //board led, just for fun
00004 
00005 Serial pc(USBTX, USBRX); // tx, rx pc control over usb
00006 
00007 uint16_t gn = 0; //position to move to
00008 uint16_t gp = 0; //current position
00009 uint16_t temperature = 255; //hardcoded for now //TODO
00010 
00011 bool move = false;
00012 
00013 uint16_t step_delay = 256;
00014 
00015 //minimum motor speed that will get doubled 5 times to result maximum motor speed
00016 //eg: for a value of 16 there will be 5 speeds as follows 16*1,16*2,16*4,16*8,16*16
00017 //eg: for a value of 16 there will be 5 speeds as follows 16,32,64,128,256
00018 uint8_t min_motor_pps = 16; //TODO use max pps since it might be more intuitive?
00019 
00020 
00021 char ml_in[256];
00022 uint8_t idx = 0;
00023 
00024 Thread serial_thread, motor_thread;
00025 Ticker m_speed;
00026 
00027 void led_blink()
00028 {
00029     while (true) {
00030         led = !led;
00031         wait(1);
00032     }
00033 }
00034 
00035 
00036 //motor control with MP6500 https://www.pololu.com/product/2968
00037 //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
00038 // https://www.pololu.com/product/2968#lightbox-picture0J8398;main-pictures , 1 kHz or greater, I2 set to low 
00039 //D2,D3,D4,D5,D6,D7,D8,D9 - DIR, STEP, SLP, I2, I1, MS2, MS1, EN
00040 
00041 DigitalOut dir(D2);
00042 DigitalOut step(D3);
00043 DigitalOut slp(D4); //pull high to enable operation
00044 DigitalOut i2(D5); //set low to enable pwm power control
00045 PwmOut i1(D6); //MP6500 power limit control
00046 DigitalOut ms2(D7); //D7 and D8 are PC_14 and PC_15 N/C oscillator pins, hence this is full step only //TODO
00047 DigitalOut ms1(D8); //set low for FULL or high for HALF, only use MS1 to be moonlite compliant ?
00048 DigitalOut en(D9); //pulled low by the motor driver, default enables operation
00049 
00050 float motor_max_amps = 0.33f;
00051 
00052 float pw = (motor_max_amps-2.2f)/-2.079f; //https://www.pololu.com/product/2968#lightbox-picture0J8398;main-pictures
00053 
00054 void mp6500() //TODO enable/disable motor
00055 {
00056     dir = 0;
00057     step = 0;
00058     slp = 1;
00059     i2 = 0;
00060     i1.period(0.001f); //1kHz period
00061     i1.write(1.0f); //start with lowest power since we're idle
00062     ms2 = 0;
00063     ms1 = 1;
00064     en = 0;
00065 }
00066 
00067 
00068 void m_step()
00069 {
00070 
00071     //while (true) {
00072 
00073         if(move) {
00074             
00075             i1.write(pw); //set defined current motor while moving
00076             
00077             if(gp > gn) {
00078 
00079                 dir = 0;
00080                 wait_us(1);
00081                 //led = !led;
00082                 step = !step;
00083                 wait_us(1); //mp6500
00084                 //led = !led;
00085                 step = !step;
00086                 wait_us(1);
00087                 //https://os.mbed.com/docs/v5.9/mbed-os-api-doxy/mbed__wait__api_8h_source.html use Thread::wait()?
00088                 //wait((step_delay/1.024)/min_motor_pps/250);
00089                 gp--;
00090 
00091             } else if (gp < gn) {
00092 
00093                 dir = 1;
00094                 wait_us(1);
00095                 //led = !led;
00096                 step = !step;
00097                 wait_us(1);
00098                 //led = !led;
00099                 step = !step;
00100                 wait_us(1);
00101                 //wait((step_delay/1.024)/min_motor_pps/250);
00102                 gp++;
00103 
00104             } else {
00105 
00106                 step = dir = 0;
00107                 wait_us(1);
00108 
00109                 i1.write(1.0f); //set minimum controller power while holding, keeps motor cool and still provides a nice holding torque, ~120ma
00110 
00111                 move = false;
00112 
00113             }
00114 
00115         }
00116 
00117     //}
00118 
00119 }
00120 
00121 
00122 
00123 //http://indilib.org/media/kunena/attachments/1/HighResSteppermotor107.pdf
00124 void read_serial()
00125 {
00126 while(true){
00127     if(pc.readable()) {
00128         char c = pc.getc();
00129 
00130         switch (c) {
00131             case '#':
00132 
00133                 switch (ml_in[0]) {
00134                     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.
00135                         break; //TODO
00136                     case 'F':
00137                         switch (ml_in[1]) {
00138                             case 'G': //N/A Go to the new position as set by the ":SNYYYY#" command.
00139                                 move = true; //runs motor();
00140                                 break;
00141                             case 'Q': //N/A Immediately stop any focus motor movement.
00142                                 move = false;
00143                                 break;
00144                             default:
00145                                 break;
00146                         }
00147                         break;
00148 
00149                     case 'G':
00150                         switch (ml_in[1]) {
00151                             case 'B': // Get the backlight value
00152                                 pc.printf("00#");
00153                                 break;
00154                             case 'C': //XX# Returns the temperature coefficient where XX is a two-digit signed (2’s complement) hex number.
00155                                 pc.printf("02#");
00156                                 break;
00157                             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
00158                                 pc.printf("%02X#", 512 / step_delay); //TODO? we sleep for step_delay*step_delay_multiplier microseconds between steps
00159                                 break;
00160                             case 'H': //00# OR FF# Returns "FF#" if the focus motor is half-stepped otherwise return "00#"
00161                                 //pc.printf("00#"); //TODO
00162                                 pc.printf("%02X#", ms1 * 255);
00163                                 break;
00164                             case 'I': //00# OR 01# Returns "00#" if the focus motor is not moving, otherwise return "01#"
00165                                 pc.printf("%02X#", move);
00166                                 break;
00167                             case 'N': //YYYY# Returns the new position previously set by a ":SNYYYY#" command where YYYY is a four-digit unsigned hex number
00168                                 pc.printf("%04X#", gn); //TODO use this to move the motor
00169                                 break;
00170                             case 'P': //YYYY# Returns the current position where YYYY is a four-digit unsigned hex number.
00171                                 pc.printf("%04X#", gp); //TODO update gp with actual motor data
00172                                 break;
00173                             case 'T': //YYYY# Returns the current temperature where YYYY is a four-digit signed (2’s complement) hex number.
00174                                 pc.printf("%04X#", temperature * 2); //indi_moonlite_focuser returns the temp/2, dunno why, dont care
00175                                 //pc.printf("0019#"); //should be 25c but is 12.5c in indi_moonlite control panel
00176                                 break;
00177                             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.
00178                                 pc.printf("01#");
00179                                 break;
00180                             default:
00181                                 break;
00182                         }
00183                         break;
00184 
00185                     case 'S':
00186                         switch(ml_in[1]) {
00187                             case 'C': //N/A Set the new temperature coefficient where XX is a two-digit, signed (2’s complement) hex number.
00188                                 break; //TODO
00189                             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.
00190                                 step_delay = 512 / strtol(ml_in + 2, NULL, 16);
00191                                 m_speed.attach(&m_step, (step_delay/1.024)/min_motor_pps/250);
00192                                 break;
00193 
00194                             case 'F': //N/A Set full-step mode.
00195                                 ms1 = 0;
00196                                 break;
00197 
00198                             case 'H': //N/A Set half-step mode.
00199                                 ms1 = 1;
00200                                 break;
00201 
00202                             case 'N': //N/A Set the new position where YYYY is a four-digit unsigned hex number.
00203                                 gn = strtol(ml_in + 2, NULL, 16); //read ml_in, discard 2 chars, convert to long, set gn
00204                                 break;
00205 
00206                             case 'P': //Set the current position where YYYY is a four-digit unsigned hex number.
00207                                 gp = strtol(ml_in + 2, NULL, 16);
00208                                 break;
00209 
00210                             default:
00211                                 break;
00212                         }
00213                         break;
00214 
00215                     case '+': //N/A Activate temperature compensation focusing.
00216                         break; //TODO
00217                     case '-': //N/A Disable temperature compensation focusing.
00218                         break; //TODO
00219 
00220                     case 'P':
00221                         break;
00222 
00223 //                    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°
00224 //                        break; //TODO
00225 
00226                     default:
00227                         break;
00228                 }
00229                 break;
00230 
00231             case ':':
00232                 idx=0;
00233                 memset(ml_in, 0, 8);
00234                 break;
00235 
00236             default:
00237                 ml_in[idx++] = c;
00238                 idx %= 8;
00239                 break;
00240         }
00241 
00242 
00243 
00244     }
00245 }//while true
00246 }
00247 
00248 
00249 int main()
00250 {
00251     mp6500();
00252 
00253     //pc.attach(read_serial, Serial::RxIrq);
00254     serial_thread.start(&read_serial);
00255 
00256     //motor_thread.start(motor);
00257     m_speed.attach(&m_step, (step_delay/1.024)/min_motor_pps/250);
00258 
00259 
00260     while(true) {
00261         Thread::wait(1);
00262     }
00263 
00264 }