Got a new project for work
Ok i have been tasked with designing a simulator/tester for a gyrocompass converter. This gear will accept a wide gamut of input signals from an old analogue gyro and convert it to NEMA0183 data for use in various navigational equipment. What i started doing was working with the step-by-step portion of the inputs. The system under test will accept a signal between 20v to 100vdc. This happens on three wires with one extra wire for GND (S1, S2, S3, REF) I figure an optoisolator and a common emmiter set up would be sufficient to take the 3.3vdc from the prop to the required input voltage. Current draw on the inputs is unknown at this point but i wouldn't imagine it would be much. The signals are as follows:
step # S1 S2 S3
1 H L L
2 H H L
3 L H L
4 L H H
5 L L H
6 H L H
This is all set up in a DAT table using byte sized binary and using a repeat loop it seams to light up the lights on my Prop BOE pretty well and in order.
Here is the issue: The unit under test requires a 36X step by step meaning all 6 steps will be cycled through before you increase by one degree. 216 steps in total. I am trying to display a mathematicaly calculated "current Heading" and compare it with the unit under test's heading. I need this to be accurate to the 1ths of a degree. The math doesn't seem so simple as each step = .00629 degrees??? how can i do this?
step # S1 S2 S3
1 H L L
2 H H L
3 L H L
4 L H H
5 L L H
6 H L H
This is all set up in a DAT table using byte sized binary and using a repeat loop it seams to light up the lights on my Prop BOE pretty well and in order.
DAT states byte %100, %110, %010, %011, %001, %101
Here is the issue: The unit under test requires a 36X step by step meaning all 6 steps will be cycled through before you increase by one degree. 216 steps in total. I am trying to display a mathematicaly calculated "current Heading" and compare it with the unit under test's heading. I need this to be accurate to the 1ths of a degree. The math doesn't seem so simple as each step = .00629 degrees??? how can i do this?

Comments
This with give you tenths of degrees. Note that the maximum number of steps is going to be 3,414,123 ( 2^31 / 629).
steps := degree * stepType * 6 'Calculate steps needed to shift heading if dir == 1 'Coming right repeat x from 0 to steps 'Loop cycles the steps necissary to shift head to desired head. Changes current head outa[0..2] := states[i] 'Looks up data table for next state and outputs it to pins states ++ 'increments to next state if states > 6 'cycles state count to 0 if states are more than 6 states := 0 decCurHead ++ 'increment decimal heading if decCurHead > 216 decCurHead := 1 currentHead ++ if currentHead > 359 currentHead := 0 pst.str(string("Current Head is: ")) pst.dec(currentHead) pst.str(string(".")) pst.dec(decCurHead) pst.newline clk.pauseMsec(100) 'pause used to slow program down used for slew ratei would like to replace the decCurHead ++ with some sort of function that will increas the decimal variable. I am just not sure that after 80 degrees of slewing the heading will be correct.
I am not sure I understand your explanation. I am guessing that the 6 states are the drive signals for a motor. It sounds like you are saying that you have to step through the states %100, %110, %010, %011, %001, %101 thirty six times (a total of 216 steps) to turn the gyro 1 degree. Is this correct?
If this is correct where does the 0.00629 degrees per step come from. If there are 216 steps per degree I get 0.004629629 degrees per step. Is this just a typo?
Of course if the gyro turns in both directions this would have to be accounted for in the counting and calculations.
After looking at your code more carefully it appears you are already doing what I suggested but you may not be taking the correct number of steps in the loops. Hard to be sure without seeing all the code.
you are correct sir. that was a typo thank you for pointing that out. also after working out some numbers i found that i could just increment my decimal value by 0.125 every 27 steps and then trunicate the value to show only the tenths place. I am going to work with that some and see what i come up with. I haven't posted the whole code yet because it is in a state of embarrasing disarray. I will try to clean it up and add the solution i am talking about. i am also going to write it so that it will use the serial terminal object for user input and to watch the numbers shift. That way people can upload it and "see" what im talking about. This problem is kinda hard to explain. You are correct and incorrect about it driving a motor. The gyrocompas converter is just a peice of equipment that converts those stepped signals to a nema HDT string. As the code moves along i will include something to watch the nema sentences and once the prop has completed the slewing process it will look at the nema sentences from the converter and return an error. Thank you for your help everyone. Please let me know if there is any more insite into this project. I have to get this up and running as soon as I can as this peice of equipment has lost any commercial repair and now i am the sole sorce for repair and the broken parts are mounting up.
As an example, let's say the current heading is 21300 steps. This is (21300*3600 + 77760/2)/77760 = 986 tenths of a degree, or 98.6 degrees. Now let's say you want to move to 101.3 degrees. This heading is (1013 * 77760 + 1800)/3600 = 21881 steps. So you would need to move (21881 - 21300) = 581 steps.
DAT org 0 StepCtrl mov mask, S1 'Store S1 pin to mask or mask, S2 'Include S2 in mask or mask, S3 'Include S3 in mask mov dira, mask 'Make pins used outputs mov tmp, par 'Load tmp with steps address mov stepsadd, tmp 'Load steps address into stepsadd add tmp, #4 'Move pointer to next hub variable mov diradd, tmp 'Load dir address into diradd add tmp, #4 'Move pointer to next hub variable mov slewadd, tmp 'Load slew address into slewadd mov outa, state5 'Initilize outputs to starting state loop rdlong Osteps, Stepsadd 'Get Remaining steps from hub ram tjz Osteps, #Loop 'If Rsteps = 0 then jump to loop and try again rdlong Odir, diradd 'Get Direction rdlong Oslew, Slewadd 'Get Rate of change mov time, cnt 'Record current system counter into time var add time, Oslew 'Add the delay to the time var Steploop tjz Osteps,#loop 'Go back and read variables if stepping is complete waitcnt time, Oslew 'Wait until delay has passed and setup for next wait command 'some code that selects which step to go to 'Has to store the current step 'Has to use dir variable to know which one to go to step0 mov outa, state0 'Output state 0 to pins sub Osteps, #1 'Decrement Ostates wrlong Osteps, Stepsadd 'Write steps remaining to hub ram jmp #Steploop step1 mov outa, state1 sub Osteps, #1 wrlong Osteps, Stepsadd 'The outa instructions here do not account for jmp #Steploop 'the pin mask and should do so step2 mov outa, state2 sub Osteps, #1 wrlong Osteps, Stepsadd jmp #Steploop step3 mov outa, state3 sub Osteps, #1 wrlong Osteps, Stepsadd jmp #Steploop step4 mov outa, state4 sub Osteps, #1 wrlong Osteps, Stepsadd jmp #Steploop step5 mov outa, state5 sub Osteps, #1 wrlong Osteps, Stepsadd jmp #Steploop jmp #loop 'Jumps to Loop S1 long |< 0 'Pin used for S1 output S2 long |< 1 'Pin used for S2 output S3 long |< 2 'Pin used for S3 output tmp long 0 'Tmp variable used for setting up variable addresses Osteps long 0 'Used for remaining steps Odir long 0 'Used to dictate direction of the steps Oslew long 0 'Used for waitcnt related to slew rate holds number of clock ticks Stepsadd long 0 'Address of steps in hub ram Diradd long 0 'Address of direction in hub ram Slewadd long 0 'Address of slew rate in hub ram mask long 0 'Used to store pin mask time long 0 'Used in waitcnt stores system time + slew rate in clock ticks state0 long %100 'State0 output state1 long %110 'State1 output state2 long %010 'State2 output state3 long %011 'State3 output state4 long %001 'State4 output state5 long %101 'State5 output FIT 492 'Ensures the program fitsfirst way variable might hold 36. The screen should display "36"
second way variable might hold 13. The screen should display "013" the end result is to have a heading value of something like 3264 in a variable and display "326.4" on the display and if the variable had 902 display "090.2" on the lcd.
I know it was long and i apologize. I haven't updated this thread in a while and a lot of time has gone into this project. If interested I could post some code. I am acctually considering posting the quadrature object on the OBEX after some scrutinizing of course
repeat dp ' Shift all bytes that need shifting to the right one place dp_buffer[index --] := dp_buffer[index - 1] ' Shift 1 place to the right dp_buffer[index] := (".") ' Insert decimal point else ' 0 insertion req'd in addition to decimal point repeat numDigits ' Shift all bytes that need shifting to the right dp_buffer[index-- + dp - numDigits + 1] := dp_buffer[index - 1] repeat (dp - numDigits) ' Insert zeros as req'd dp_buffer[index-- + dp - numDigits + 1] := ("0") dp_buffer[1] := (".") ' Insert decimal point dp_buffer[0] := ("0") ' Insert leading "0"The data needs to be shifted 1 + the number of leading zeros to the right, and the decimal point and leading zeros inserted. The amount to shift can be calculated by subtracting the index (actual number of digits) from 5 (number of digits you want + decimal point). The number of leading zeros to insert is 1 less than the shift amount.
The relevant code looks like this:
PUB decx(value, digits) | i '' Prints zero-padded, signed-decimal string '' -- if value is negative, field width is digits+1 decl(value,digits,2) PUB decl(value,digits,flag) | i, x '' DWD Fixed with FDX 1.2 code digits := 1 #> digits <# 10 x := value == NEGX 'Check for max negative if value < 0 value := ||(value+x) 'If negative, make positive; adjust for max negative tx("-") 'and output sign i := 1_000_000_000 if flag & 3 if digits < 10 ' less than 10 digits? repeat (10 - digits) ' yes, adjust divisor i /= 10 repeat digits if value => i tx(value / i + "0" + x*(i == 1)) value //= i result~~ elseif (i == 1) OR result OR (flag & 2) tx("0") elseif flag & 1 tx(" ") i /= 10If you're LCD object contains a version of FullDuplexSerial, you may already have these methods. If not, you should be able to add them. I think you can also do this using the Numbers object:
I think this method is a bit more complicated but I think it has more options (space, commas, etc). Have a look at the Numbers object. It has a large table that details all the different formats.
Congrats on your success.
Peter
Stepper CTRL.spin
So the project is going well. The user interface is almost done just polishing it off and trying to correct some bugs. It seems that the first object i wrote is not working as it should. guess i didn't test it enough before using it to develop my UI. For the life of me i can not figure out why it behaves the way it does. Firstly i have the Prop BOE and i have B1-P0 / G1-P1 / R1-P2 connections made to visualize what is happening. I built this quick demo object to run the "stepper CTRL" object. first you call the start method and pass it the step type (1,36,180). Secondly with everything initilized at 0 including your heading you can then call the goto method and it will do some calculations (not fully ironed out) and store that into the ordrHead variable. the cog will read this variable and slew then calculate which direction to slew and how fast to do it. everything works fine if you use a moving right type of heading shift as the first thing to do. if you move left first then it seams P2 stays high and the heading variable changes which means its getting through the step changing instructions but it never seams to output the correct patterns on the leds. Kinda weird youll have to see for yourself. I uploaded the source code of both programs for your reading pleasure. Be kind like i said its my first program.
something like that but maybe more customized for each "state" to load or build a loop that each state change would go through. the output wave form while "stepping" through the heading should look like three squarewaves 120degrees phase shifted so that only two of the output pins are high at once. This generates a 6 bit grey code of sorts that the gyrocompass converter uses to generate NMEA0183 sentences for VHW and HDT
The above listed code.. is it nessisary or should i just use the MOV command assuming i have other pins doing other things elsewhere in the program? ie when using the MOV command and using a literal in the source field of 3 bits in length, will it only effect just those 3 bits or whill the MOV command set the unspecified bits to lows and effect the entire 32 bits of the OUTA?
I got all the circuitry all hooked up and started playing around with it and noticed one out standing problem. When i use a slew rate of 10 degrees or less the converter follows exactly. When i get closer to the converters upper limit of 30 degrees per second it seams to have an error inbetween 1 to 5 degrees. I think that this is because when i hit the "go" button it immediatly is outputing the pulses at full slew rate. Of course this is different than how a boat acts. I think i need to add the function of a ramp speed into my pasm code. Does anyone have any pointers on how to implement this into my code?
exactly! well done.
As long as the cog has just the used pins as output you are fine.
After looking at your pasm I think the most easy way would be to change the slew rate to create ramping. Just start and end the first and last (or 2 each) steps with double slew-rate. (2 x waitcnt)
So go 'half speed' before 'full speed'. This might already do it, its more like '2 steps' and not a ramp.