The MPHASE box

Thread Starter

nsaspook

Joined Aug 27, 2009
7,181
A fairly simple serial command response controller using the PIC18F45k80, max232 RS-232 converter and mainly leftover previous project parts for a automatic digital servo amplifier programmer.
https://github.com/nsaspook/mphase/blob/master/srhmi_e.pdf

The software is programmed in XC8 2.0 with MCC 3.66 for the boilerplate module configuration templates. Version 2.0 has C99 compatibility so you can use non-constant initializers in structures and/or designated initializers with a few other added goodies over old C90 ANSI C.
C:
// Display, command/response strings
#include "../app.h"
static const struct CR_DATA CrData[] = {
{
.headder = "MCHP Tech MP V",
.bootb = "Boot Button Pressed ",
.buttonp = "When done press OK ",
.done = "Resolver value SET ",
.blank = " ",
.c1 = "booting...",
.r1 = "booting...",
.c2 = "HVER\r\n",
.r2 = "Drive 70",
.c3 = "MPOLES\r\n",
.r3 = "24",
.angle = ".",
.diskmove = "Wait, moving",
.error = "Reboot SPIN AMP\r\n",
.s1 = "Press Clear Error on",
.w1 = "Spin Motor SCREEN ",
.s2 = "Press FLIP UP on ",
.w2 = "MID LEVEL SCREEN ",
.s3 = "Power Cycle Spin AMP",
.w3 = "with Scan Safety Key",
.dis = "DIS\r\n",
.msg2 = "MSG 2\r\n",
.mpoles0 = "MPOLES 0\r\n",
.mphase90 = "MPHASE 90\r\n",
.opmode2 = "OPMODE 2\r\n",
.en = "EN\r\n",
.t35 = "T 35\r\n",
.pfb = "PFB\r\n",
.msg0 = "MSG 0\r\n",
.mnumber0 = "MNUMBER 0\r\n",
/* CHANGE THIS TO THE REAL 'SAVE' COMMAND
* in the production version.
*/
#ifdef PRODUCTION
.save_parm = "SAVE\r\n",
#else
.save_parm = "XXXXX\r\n",
#endif
.line1 = "\eO\x01\x01%s",
.line2 = "\eO\x01\x02%s",
.line3 = "\eO\x01\x03%s",
.line4 = "\eO\x01\x04%s",
.line_d = "\eO\x01\x01%s %d ",
.line_h = "\eO\x01\x04%s%s",
},
{
.headder = " ",
}
};

static const struct RS_DATA RsData[] = {
{
.line_m = " MPHASE %d \r\n",
.line_o = "\eO\x01\x02 offset %d",
.line_s = "%s",
},
{
.line_m = " ",
}
};

// set strings to the proper controller
const struct CR_DATA *cr_text = &CrData[MC_SS600];
const struct RS_DATA *rs_text = &RsData[MC_SS600];

// mainline code fragment using const string data.
switch (appData.state) {
//Initial state
case APP_INITIALIZE:
if (APP_Initialize()) {
appData.state = APP_CONNECT;
display_ea_init(700);
BUZZER_OFF;
display_ea_ff(1);
display_ea_cursor_off(1);
display_ea_version(1000);
StartTimer(TMR_DIS, DIS_REFRESH_MS);
} else {
appData.state = APP_INITIALIZATION_ERROR;
}
break;
//Initialization failed
case APP_INITIALIZATION_ERROR:
appData.error_code = ERROR_INITIALIZATION;
BUZZER_ON;
break;
case APP_CONNECT:
appData.state = APP_COMMUNICATE;
if (MC_ReceivePacket(appData.receive_packet)) { // received data from controller
clear_MC_port();
BUZZER_ON;
appData.got_packet = false;
if (strstr(appData.receive_packet, cr_text->r1)) { // power restart
appData.mc = MC_BOOT;
appData.got_packet = true;
}
if (strstr(appData.receive_packet, cr_text->r2)) { // hardware version
if (appData.mc == MC_BOOT) {
appData.mc = MC_DRIVE;
} else {
appData.mc = MC_INITIALIZE;
}
appData.got_packet = true;
}
if (strstr(appData.receive_packet, cr_text->r3)) { // motor poles
if (appData.mc == MC_DRIVE) {
appData.mc = MC_SETUP;
} else {
appData.mc = MC_INITIALIZE;
}
appData.got_packet = true;
}
}
break;
// end fragment
I must say that XC8 2.0 has lots of quirks with code memory management and will give 'psect' (can't find memory section) errors if 32-bit floats are used. The best way about this is to isolate all floating point code, variables and operations in a separate C module so the compiler can optimize it separately from mainline code.

C:
#include "pfb.h"

// resolver angle data from controller parser

uint16_t get_pfb(const char * buf)
{
float offset, mphase, offset_whole;
char *token, pfb_ascii[MC_RX_PKT_SZ + 2], s[2] = " ";

strcpy(pfb_ascii, buf); // make a local copy of the data
token = strtok(pfb_ascii, s); // start token search
token = strtok(NULL, s); // look for the second number

if (token != NULL) {
mphase = atof(token);
offset = ((MOTOR_POLES / MOTOR_PAIRS) * mphase) / 360.0;
offset_whole = trunc(offset); // get the whole part with no rounding
offset = (offset - offset_whole)*360.0; // extract fractional part for angle offset calc
/* need to round and convert data to integer */
return(uint16_t) roundf(offset);
} else
return(666);
}

Simple one-sided solder pad board with 28awg direct wiring between components.

The box eliminated the need for a laptop with serial port and terminal program for the zero procedure.

Still need to add the serial port connector to the box instead of a ribbon cable. :(


Complete software and most of the doc's used. Still needs some error checking work.

https://github.com/nsaspook/mphase/tree/xc2.05_version
C:
#include "mcc_generated_files/mcc.h"
#include "app.h"
#include "config.h"

/*
* Main application MPHASE
* A simple command, response parser that generates the proper offset angle
* to program a direct drive servo motor system with a resolver for the
* drive angle rotation/speed feedback. Serial port 1 sends and receives data on the
* servo control port. Serial port 2 updates a 4*20 LCD display.
* Both serial ports are 9600 baud with no flow control.
*
* There are two control buttons for the operator interface LCD. The top button near the
* display is the 'OK' that should be pressed after the required action on the
* LCD display has been executed. The second smaller button near the bottom is
* the 'BOOT' button that allows the operator to bypass the wait for the
* servo controller auto boot sequence so the operator can program an already running
* motor control system. The 'BOOT' button can also reboot the MHPASE box by quickly pressing
* the 'BOOT' button and then the 'OK' button in sequence.
*
* Normally the servo controller is powered off first for a resolver calibration.
* The MPHASE box serial cable with DB9 connector is attached to the servo DB9 serial port,
* power is supplied to the MPHASE box via the attached power brick and
* then 'RUN' power is switched on to the servo controller and motor.
* The MPHASE box display should display a series of prompts with audio beeps
* if the serial connection is correct and the servo responds in the expected manner.
*/
void main(void)
{
// Initialize the device
SYSTEM_Initialize();
PIN_MANAGER_IOC();

// If using interrupts in PIC18 High/Low Priority Mode you need to enable the Global High and Low Interrupts
// If using interrupts in PIC Mid-Range Compatibility Mode you need to enable the Global and Peripheral Interrupts
// Use the following macros to:

// Enable high priority global interrupts
INTERRUPT_GlobalInterruptHighEnable();

// Enable low priority global interrupts.
INTERRUPT_GlobalInterruptLowEnable();

// Disable high priority global interrupts
//INTERRUPT_GlobalInterruptHighDisable();

// Disable low priority global interrupts.
//INTERRUPT_GlobalInterruptLowDisable();

// Enable the Peripheral Interrupts
INTERRUPT_PeripheralInterruptEnable();

// Disable the Peripheral Interrupts
//INTERRUPT_PeripheralInterruptDisable();


while (true) {
APP_Tasks();
}
}
C:
// This is a guard condition so that contents of this file are not included
// more than once.
#ifndef XC_HEADER_TEMPLATE_H
#define XC_HEADER_TEMPLATE_H

#include <xc.h> // include processor files - each processor file is guarded.

/*
* timer 0: key bounce and delays
* timer 1: software timers on low interrupt vector
* timer 3: speaker sound generation
* RA5 speaker driver pin
* RA0 LED driver pin
* usrt 1: motor controller comms
* uart 2: LCD comms
* EXT INT 0: SW 1 push detect
* EXT INT 1: SW 2 push detect
* EXT INT 2: SW 3 push detect
* EXT INT 3: SW 4 push detect
*/

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

// TODO If C++ is being used, regular C code needs function names to have C
// linkage so the functions can be used by the c code.

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* XC_HEADER_TEMPLATE_H */
 
Last edited:

Thread Starter

nsaspook

Joined Aug 27, 2009
7,181
This is typical motor that MPHASE will calibrate the resolver for.
IMG_20190703_153325027.jpg
Direct driver motor with encoder for slow speed indexing and resolver for high speed spin angle detection.
IMG_20190703_153335832.jpg
Vacuum chamber motor mount.


IMG_20190721_074216425_HDR.jpg
https://www.microchip.com/wwwproducts/en/PIC18F47K42
IMG_20190722_151137470.jpg
With the prototype software done the hardware is being moved to a new SIB board (pic18f47k42) designed to handle several types of diagnostic and routine maintenance control units.
IMG_20190722_152400217_HDR.jpg
 
Last edited:
Top