Model Boat Mayhem

Technical, Techniques, Hints, and Tips => The "Black Arts!" ( Electrics & Electronics ) => Topic started by: megatron on August 04, 2014, 07:22:46 pm

Title: Help writing pic code
Post by: megatron on August 04, 2014, 07:22:46 pm
Hi shipmates
I have built a boiler control unit similar in operation to a Cheddar ABC unit using opamps and timer chips. This unit works well but is on the bulky side.
I would now like to scale it down using a pic or maybe a picaxe chip.
Is there anyone out there who could help with writing the code for this. I am not looking for someone to write the code only to hold my hand and point me in the right direction. I have bought a book to try and teach myself but I don't understand a word of it.
regards
Stew
Title: Re: Help writing pic code
Post by: dreadnought72 on August 05, 2014, 12:10:46 am
I'd love to be able to help. I'm learning/developing working code for the Arduino: if you've not set your heart on Picaxe then DO dip a toe into the world of Arduino - you might be surprised at what it can do!

PM me your email address and we'll take it from there (and report back here!)

Best wishes,

Andy
Title: Re: Help writing pic code
Post by: megatron on August 05, 2014, 08:03:01 am
Hi Dreadnought72
Thanks for your offer of help.
I've looked at the arduino but it is simply too large, even without the board the actual chip is almost as large as the enclosure I want to put it in.
You may still be able to help me with the coding though. What language do you use to code the arduino?

regards
Stew
Title: Re: Help writing pic code
Post by: dreadnought72 on August 05, 2014, 10:04:52 am
The Arduino Nano is 0.73" x 1.70" ... how small do you need to go!?  :-)

The language is a form of C/C++ and pretty straightforward for anyone with a toe in the world of Javascript or ActionScript.

Thanks for the PM - I'll send you my email address and we'll take it from there.

Andy
Title: Re: Help writing pic code
Post by: Time Bandit on August 05, 2014, 12:02:59 pm
If you change from PIC to AVR I could be able to help.


I have learned BASCOM a year ago, which is a basic dialect.
But also the Arduino code is able to flash normal AVR.
Arduino is mainly the hardware around the mikrocontroller.

Would be a good idea if you describe what the control has to do incl. Inputs and outputs.
Then I can check which chip to choose and how much effort it would be to programm it.
Title: Re: Help writing pic code
Post by: richald on August 05, 2014, 05:16:57 pm
I'm with dreadnought72 - the Arduino is possibly the best way to go -
I have been doing a bit of programming on it and I am impressed with
its capabilities. It is also cheap if you go to somebody like Hobbyking!

Arduino Nano V3.0 Microcontroller Board (http://www.hobbyking.com/hobbyking/store/__46902__Arduino_Nano_V3_0_Microcontroller_Board.html) Ģ5.48 !

Richard
Title: Re: Help writing pic code
Post by: Time Bandit on August 05, 2014, 05:50:35 pm
I have to admit, the ARDUINO is a very good development tool and for beginners probably the best to start with, since you just have to deal with programming and not with designing the surrounding circuit.
At least the hardware (I never took a deeper dive in programming it) is designed pretty perfect, if you need it.

BUT,
basically itīs just an ATMEL AVR with some hardware around it. The hardware around it, of which 90% is useless in 90% of the cases in RC-modelling, makes it also expensive.
Who needs a USB in a model?
Compared to a Atmega8 at Ģ0.5  in my opinion itīs too expensive and too overpowered for simple applications in RC models.
In addition to this you can use only 4? of 100? different AVR controllers with a lot of different features.
For example I really like the small Attiny due to their abilities like high frequency PWM and DAC capabilities.

I canīt really judge the programming since I never used more than 10 min to check on some code.
But what I experienced is a lot of "inexplicable" errors you read of...
The start is very easy since you can use a lot of "premanufactured" libraries, but on some point you have to understand what these libraries do, to use the controller correctly (e.g. using the same timer twice is not a very bright idea).
And thatīs the problem what you can read in several forums every day "the servo library is not working correctly".
The problem is always that people are not able to read the datasheets of the controllers or just donīt care what happens in several libraries. Thatīs why these threads are called "timer1 threads"  :}

My summary:
If you want to develop you own working mikrocontroller applications and you are able to handle the (pretty easy) circuits outside the controller (which I guess should be no problem if you can develop a circuit with opamps and timer chips) youīl better go with single mikrocontroller chips and "C" or "BASCOM" or even "Assembler".
For people who ever saw basic, BASCOM is probably the easiest language to learn. If you are used to "C" or "C++" it makes no sense to change.
This does also appy if you want minimalistic hardware (package size and price).

If you want a perfect development environment with incredibly fast learning progress on the first steps, youīll better go with ARDUINO.

Still waiting for some details on your project  :}
Title: Re: Help writing pic code
Post by: fpravenscroft on August 05, 2014, 06:15:39 pm
hi megatron
   if you download the pick axe progamer it has a flow chart that will convert to the program
 also there is a manual that you can download
the sound systems for deisel engines are on picaxe chips
hope this helps
regards
peter
Title: Re: Help writing pic code
Post by: megatron on August 05, 2014, 07:42:42 pm
Hi everyone
The box I am hoping to use is 50x35 and as I will be building on stripboard that gives me a useable grid of 18x12. The arduino nano appears to be 18x8 so that's out of the question.
I need 5 inputs, 1 digital, 1 analogue, and 3 that could be either. I also need outputs for 2 servos and 3 leds.
I am seriously considering the picaxe 14M2 as this is fairly cheap, has a 7x4 footprint, has 12 i/o pins plenty of adc's and support in the software for outputting to servos.
They are programmed using Basic and as fpravenscroft says they will even program from a flow chart.
Has anyone used a picaxe before and if so what's the verdict.
I am still open to suggestions so if you know of something better that fits the bill let us know.
regards
Stew
Title: Re: Help writing pic code
Post by: Time Bandit on August 05, 2014, 08:16:46 pm
Programm from a flowchart (like Siemens S7?) sounds nice. Even if you once found out how to program "manually" itīs probably too time consuming.
But beware of the "Servo-out" functions, no matter what you are going to do in the end. Never saw one that worked good (despite one Arduino lib), the servo are always jittering if the code gets more complex than just controlling servoīs.
I recommend to programm it manually with a timer interrupt control.

I donīt have a better solution, just maybe the same as AVR.
Check out the Attiny44/84  http://www.atmel.com/Images/doc8006.pdf
The hardware is probably comparable, the only thing that counts for AVR in my opinion is that (at least here in germany) more people are using it and can help debugging. Also the prices should be lower. Attiny44 is less than 1€ here in germany.
Not sure how big your programm is going to be, but you have to consider if you are using basic that the programs get around twice the size as if programmed in Assembler. 2kb can get small pretty fast  %%

Not so sure about the costs of the development environment for the PICīs.
If you need no further environment this should do it to flash the AVR chip. http://www.ebay.de/itm/USB-ISP-USBASP-Programmiergerat-Programmierer-fur-Atmel-AVR-ATMEGA8-ATTiny-OPV-/281121456079?pt=Wissenschaftliche_Ger%C3%A4te&hash=item417424ffcf
Iīm not a big fan of risking my personal computer hardware by flashing directly over a serial port with some DIY programmer.




Title: Re: Help writing pic code
Post by: megatron on August 05, 2014, 08:45:33 pm
Hi Time Bandit
Yes the Attiny chips seem very similar to the picaxe chips. Similar size and price.
It all comes down to which one people know the best.
As you say 2k of program isn't a lot. I'll not know how much I need until the program is written. I had wanted to write it in assembler but I just can't get my head around it.
I hadn't heard of the Attiny chip until you mentioned it, over here the picaxe is popular as it's taught in schools.
I'll wait and see what the majority think.
Thanks
Stew
Title: Re: Help writing pic code
Post by: dreadnought72 on August 05, 2014, 09:13:54 pm
Who needs a USB in a model?

Anyone who needs to revise their code from a laptop, maybe?

Andy
Title: Re: Help writing pic code
Post by: richald on August 06, 2014, 06:48:25 am
Stew

Just out of interest, what are you intending to put on your stripboard?

I'm guessing a bit here, but most of your connections would probably
go straight onto an Arduino Nano

Richard
Title: Re: Help writing pic code
Post by: Time Bandit on August 06, 2014, 07:20:11 am
Anyone who needs to revise their code from a laptop, maybe?

Andy

Well that's why the chips have an SPI interface  %)


Back to topic.
Taught in schools? That sounds like the german school system is even worse than I ever thought.
The usage rate should be better with tge Picaxe then.






Title: Re: Help writing pic code
Post by: megatron on August 06, 2014, 11:15:14 am
Hi Richald
The stripboard will be used to mount the chip and will contain the circuitry for the sensors as well as the leds and external connections.
I've uploaded a picture of my previous boxes so you all know where we are going.
The box in the centre is a Cheddar ABC unit. The large box is my take on this, and the smaller box is a unit which only maintains boiler pressure. My goal is to make the large box the same size as the small one.
No problems then.
Stew
Title: Re: Help writing pic code
Post by: Time Bandit on August 06, 2014, 05:09:59 pm
I made some small test about the code size.
The following BASCOM code does:
- reading in 1 RC channel
- 2 Servo outputs
- reading 4 analogue Inputs
- does nothing with the input values, no calculation...

Code Size: 0,75kb which means 36% of 2kb used.

Code: [Select]
'******************************************************
'
' (c)2014 Tobias Birkner
'
'******************************************************
'Project: Cheddar ABC Clone
'
'Prozessor: Attiny44
'Bascom-Version: 2.0.7.7
'
'
'Version 1.0
'06.08.14 Test Program
'******************************************************
'
'======================================================
'System
'======================================================
'Definition Attiny
$regfile "ATTiny44.dat"

' (8Mhz)
$crystal = 8000000
$hwstack = 32
$swstack = 10
$framesize = 40

' Pin configuration
Config Pinb.2 = Input                                       'RC_channel
Config Pina.0 = Input                                       'ADC0
Config Pina.1 = Input                                       'ADC1
Config Pina.2 = Input                                       'ADC2
Config Pina.3 = Input                                       'ADC3
Config Porta.4 = Output                                     'Servo1
Config Porta.5 = Output                                     'Servo2
Config Porta.6 = Output                                     'LED
Config Porta.7 = Output                                     'LED
Config Portb.1 = Output                                     'LED

Servo1 Alias Porta.4
Servo2 Alias Porta.5
1led Alias Porta.6
2led Alias Porta.7
3led Alias Portb.1

'Konfiguration des Timer 1
Config Timer0 = Timer , Prescale = 64                       'timer to read rc channel
Config Timer1 = Timer , Prescale = 8                        'timer for servos
Config Adc = Single , Prescaler = 64 , Reference = Avcc
Start Adc
'Configuration INT0
'Interrupt bei jedem Flankenwechsel (0->1 und 1->0)
Config Int0 = Change

Dim Reading As Bit
Dim Rc_value As Word
Dim Analogueinput(4) As Word
Dim Kanal As Byte
Dim Servo(2) As Word                                        'theoretical 1000 values resolution. 64036 = Middle   +500 -500 = normal servo way 90°, increase for 180°



'Interrupt-Service-Routines
On Int0 Rc_read
On Timer1 Servoirq                                          'servo

'Enable anything
Enable Timer0
Stop Timer0
Enable Timer1
Timer1 = 64036                                              '64036 = Middle   +500 -500 = normal servo way 90°, increase for 180°
Enable Int0
Enable Interrupts

'Einmalige Aktionen vor Hauptprogramm


Servo(1) = 64035
Servo(2) = 64035



Do

Servo(1) = 0                                                'unspecified
Servo(2) = 0                                                'Unspecified
Analogueinput(1) = Getadc(0)
Analogueinput(2) = Getadc(1)
Analogueinput(3) = Getadc(2)
Analogueinput(4) = Getadc(3)
'nothing specified

Loop
End




Rc_read:                                                    'read RC Channel value (with low resolution)
If Reading = 0 And Pinb.2 = 1 Then
   Start Timer0
   Reading = 1
Else
   Stop Timer0
   Rc_value = Timer0
   Timer0 = 0
   Reading = 0
End If
Return


Servoirq:
If Kanal = 0 Then
   If Servo1 = 0 Then                                       'if port low
      Timer1 = Servo(1)                                     'timer1 on reload value
      Servo1 = 1                                            'port=1
   Else                                                     'happens at next interrupt
      Servo1 = 0                                            'port=0
      Incr Kanal                                            'next servo
   End If
End If
If Kanal = 1 Then
   If Servo2 = 0 Then
      Timer1 = Servo(2)
      Servo2 = 1
   Else
      Servo2 = 0
      Incr Kanal
   End If
End If

If Kanal = 2 Then
  Timer1 = 53536                                            'Pause for 16ms
  Kanal = 0
End If
Return
Title: Re: Help writing pic code
Post by: megatron on August 06, 2014, 05:53:20 pm
Hi Time Bandit
Is the 0.75kb the size of the basic program or the size of the compiled code?
There shouldn't be a lot more to add, only reading the inputs and turning outputs on or off, there's no real calculations to do.
Do you think doing it in less than 2kb is feasible?
Stew
Title: Re: Help writing pic code
Post by: Time Bandit on August 06, 2014, 07:31:02 pm
The compiled code  :}
But most of it is coded discrete, so if you are going to use functions like "Servo Out" it is going to need a lot more byte.
But if itīs not much more to do it should work (at least with this "style" of programming)

If you can tell me how it is working or should work Iīm going to program it.
Description like this "if input1=0 --> Servo 1 maximum angle" is enough to me.
Itīs probably a matter of only minutes for me, the bigger task is to describe it :-)
Google is not finding "cheddar abc unit".
Title: Re: Help writing pic code
Post by: megatron on August 06, 2014, 09:29:35 pm
Hi Tobias
I've sent you a PM
look for Cheddar automatic boiler control
cheers
Stew
Title: Re: Help writing pic code
Post by: afb on August 07, 2014, 02:14:41 pm
Hi Megatron

I've used most of the range of PICAXE chips including the 14M2. As an earlier reply pointed out I use PICAXE chips in my (Technobots) Engine Sound Units, plus I have made ESCs, rudder mixers, servo slower/stretchers, RC switches etc all using PICAXE. I'm also working with Arduino as I need it's speed for audio processing, and based on my experience I think that if you have done little or no programming then you'll find programming in (PICAXE) Basic is the easiest option. However, it's *interpreted* basic so the code won't run nearly as fast as compiled code that you'd use on the Arduino - but still plenty fast enough for your application I'd have thought. Again as someone pointed out, the PICAXE's built-in servo command that can run in the background is subject to 'glitching' - as all my projects are RC related I let reading of the RX input(s) set the rate of the overall program loop and use the 'pulsout' command to refresh the servo once per loop - this gives jitter free operation. I'd be happy to give you a few pointers should you decide to go the PICAXE route. Note there is a very good PICAXE Forum bursting with clever chaps eager to help.

Alan Bond
Title: Re: Help writing pic code
Post by: Time Bandit on August 07, 2014, 05:29:21 pm
Regarding the discussion about Picaxe or AVR I also read a comment about the speed of the picaxe controllers.
I wonder why it should be slower since itīs also running at 4 Mhz. It canīt be only the compilation since C-compiled code is not much smaller than basic compile code.
What I experience is, that clever assembler program code is much smaller than both of them.

Anyways,
I added the code for the described functions and deleted the readout of the reciever channel, I hope this helps a little bit ;-)
It was a little bit more work than I thought, and the size of the code increased to 2,1kb.
So NOW you have to go with AVR  {-)
It can be optimized by defining the variables different, but I think you will always scratch the maximum of the picaxe, which is not a good idea.

I really tried to make it understandable, but Iīm open to questions.
Maybe you also add your description on the functions here, that might help others.
If you want to change the pin configuration on the attiny due to your circuit layout, you just have to change the ALIAS functions and input/output settings. Just be careful with the ADC numbers, since these are fixed to a certain pin.
You canīt work with Aliases here.
TO compile the code you need BASCOM (free version up to 4kb code is enough).
Itīs probably still full of errors but I did not find the time to simulate or test it in reality.
I have to finish my 16 channel universal multi switch for 2,4 GHz radios and will be on short vacation for the next 3 days. :}

Just a few additional questions:
Is the feed tank sensor also giving an analogue output or is it "digital" low/high, I guessed the sensors a comparable and both need calibration?
And both level sensors work on the same valve/servo? Thatīs how it is programmed right now.
What should happen if both water levels are low at the same time? Bypass Valve opened and Warning LED lit I guessed? What about the gas valve?

One thing Iīm a little curious about. Do you want a 2 point regulation for the gas or or proportional regulation.
Does the pressure sensor have an linear voltage output according to pressure? If yes a proportional regulation of the servo is possible.
But I have no idea if this is necessary (would it save gas? prevent overpressure valve from letting out steam?) or not.

The setup works like this, I thought of a 2 way toggle switch, if itīs just a push switch you have to change the code.

Press Switch low (input on Attiny is connected to ground) and then power on the module with 5V --> it goes into setupmode
All 3 LED are blinking
place boiler sensor above water level and press switch to high
wait for 1s
place boiler sensor below water level and press switch to low again
1 LED stops flashing, 2 LED still flashing
place feed tank sensor above water level and press switch to high
wait for 1s
place feed tank sensor below water level and press switch to low again
1 LED stops flashing, 1 LED still flashing
Pilot flame adjustment, Servo is set to 2ms at the beginning of setupmode (what setting should the "water servo" have during setup?)
You adjust the pilot flame now
Press Switch to high, last LED stops flashing
Disconnect module from electric power
Press Switch to high
Wait for 30s
Repower the module with switch=high and it starts in normal mode with calibrated water level sensor without flashing the LED




Can you somehow calibrate the pressure sensor (with external pump, without steam pressure)? Maybe you do this once, and manually change the value before flashing the chip  (pressuresensvalue=512 = 2,5V)

And also a recommondation regarding your circuit.
Best is to separate servo and chip power (even if itīs just 2 different BEC modules)
If this is (as in most cases) not possible, do not just put a 100n cap between VCC and GND of the chip.
You need a bigger cap to decouple the interference from the servoīs and a strong power supply, otherwise you may get some very strange reactions from brown outs to erasion of the non volatile memory.

Code: [Select]
'******************************************************
'
' (c)2014 Tobias Birkner / For Non-Commercial use only
'
'******************************************************
'Project: Cheddar ABC Clone
'
'Prozessor: Attiny44
'Bascom-Version: 2.0.7.7
'
'
'Version 2.0
'1.0 06.08.14 Test Program
'2.0 07.08.14 Completed code for automatic boiler control
'******************************************************
'
'======================================================
'System
'======================================================
'Definition Attiny
$regfile "ATTiny44.dat"

' (8Mhz)
$crystal = 8000000
$hwstack = 32
$swstack = 10
$framesize = 40

' Pin configuration

Config Pina.0 = Input                                       'Boiler lvl sensor
Config Pina.1 = Input                                       'pressure sensor
Config Pina.2 = Input                                       'Pilot flame pot
Config Pina.3 = Input                                       'Feed tank lvl sensor
Config Porta.4 = Output                                     'Servo1
Config Porta.5 = Output                                     'Servo2
Config Porta.6 = Output                                     'LED
Config Porta.7 = Output                                     'LED
Config Portb.0 = Output                                     'output for FET
Config Portb.1 = Output                                     'LED
Config Pinb.2 = Input                                       'Setup Mode Switch
Portb.2 = 1                                                 'internal pullup on

Sensorcalibswitch Alias Pinb.2                              'Digital in, internal pullup switched on, but you can add an external pullup resistor
Servo1 Alias Porta.4
Servo2 Alias Porta.5
Waterlowled Alias Porta.6
Gashighled Alias Porta.7
Waterbypassled Alias Portb.1
Electricpump Alias Portb.0

'Konfiguration des Timer 1
Config Timer0 = Timer , Prescale = 1024                     'timer for hyteresis 10s
Config Timer1 = Timer , Prescale = 8                        'timer for servos
Config Adc = Single , Prescaler = 64 , Reference = Avcc
Start Adc

Dim Reading As Bit
Dim Rc_value As Word
Dim Analogueinput(4) As Word
Dim Kanal As Byte
Dim Servo(2) As Word                                        'theoretical 1000 values resolution. 64036 = Middle   +500 -500 = normal servo way 90°, increase for 180°
Dim Eedummy As Eram Byte                                    'dummy since first adress is buggy
Dim Watersensvalue(2) As Word                               'average value between "no water present" and "Water present" 1= boiler 2=feed tank
Dim Eewatersensvalue(2) As Eram Word                        'saved value in EERAM
Dim Waterpresent(2) As Byte                                 'flag for 10s delay
Dim Tensecond As Word                                       'counter to increment since timer0 is too fast at 8Mhz
Dim Pressuresensvalue As Word                               'average value between "pressure high" and "pressure low"
Dim Eepressuresensvalue As Eram Word                        'saved value in EERAM
Dim Pilotflame As Word                                      'Amount of regulation value for pilot flame
Dim Calibstate As Byte                                      'flag for setupmode
Dim Ledtoggle As Byte                                       'counter to toggle LED during setup mode

Const Smv = 64036                                           'Servo Middle Value

'Interrupt-Service-Routines
On Timer1 Servoirq                                          'servo
On Timer0 Waterirq

'Enable anything
Enable Timer0
Stop Timer0
Enable Timer1
Start Timer1
Enable Interrupts

'Initialize before main program
Servo(1)=SMV+500   '1ms pump bypass valve open
Servo(2)=SMV-500   '2ms only Pilot flame at startup

Calibstate=0
If Sensorcalibswitch = 0 Then
   Goto Calibration
End If

watersensvalue(1)=EEwatersensvalue(1)
Waitms 10
If watersensvalue(1)=0 then             'only for first startup, if no calibration value is present
   watersensvalue(1)=512
End IF
watersensvalue(2)=EEwatersensvalue(2)
Waitms 10
If watersensvalue(2)=0 then             'only for first startup, if no calibration value is present
   watersensvalue(2)=512
End IF
 'pressuresensvalue=EEpressuresensvalue 'not needed right now
 'waitms10 'not needed right now
pressuresensvalue=512




'main program

Do
'read ADC
Analogueinput(1) = Getadc(0)
Analogueinput(2) = Getadc(1)
Analogueinput(3) = Getadc(2)
Analogueinput(4) = Getadc(3)

'Check if water present with optical sensor
If Analogueinput(1) <= Watersensvalue(1) Then               'ADC0
   Servo(1) = Smv + 500                                     '1ms bypass valve open
   Waterpresent(1) = 1
   Waterlowled=0
   Electricpump=0
   Tensecond = 0
   Stop Timer0
Endif
If Analogueinput(1) > watersensvalue(1) then
   Start Timer0
End if


'Check Feed Tank Level Sensor
If Analogueinput(4) <= Watersensvalue(2) Then               'ADC3
   WaterbypassLED=0
   waterpresent(2)=1
Endif
If Analogueinput(4) > Watersensvalue(2) Then
   Servo(1) = Smv + 500                                     '1ms pump bypass valve open, overwrites "bypass valve closed due to low lvl in boiler"!!!
   waterpresent(2)=0
   WaterbypassLED=1
End If

     'alternate programming with digital sensor voltages
     'If Tanklvlsens=0 then
     '   WaterbypassLED=0
     '   waterpresent(2)=1
     'Else
     '   Servo(1)=SMV+500   '1ms pump bypass valve open
     '   WaterbypassLED=1
     '   waterpresent(2)=0
     'End IF



'Boiler pressure regulation
'Read and calculate Pilot Flame Pot
Pilotflame = Analogueinput(3) / 10                          'ADC2, makes a maximum of 102 = 0,102 ms, by dividing it just by 5 it will reach 20° max

If Analogueinput(2) <= Pressuresensvalue Then               'ADC1
   Servo(2) = Smv + 500                                     '1ms
   GASHIGHLED=1
End If
If Analogueinput(2) > pressuresensvalue then
   Servo(2) = Smv - 500                                     '2ms
   Servo(2) = Servo(2) + Pilotflame                         'if servo is jittering use another variable to combine these calculations and give out only 1 value
   Gashighled = 0
End If


Loop
End


Servoirq:
If Kanal = 0 Then
   If Servo1 = 0 Then                                       'if port low
      Timer1 = Servo(1)                                     'timer1 on reload value
      Servo1 = 1                                            'port=1
   Else                                                     'happens at next interrupt
      Servo1 = 0                                            'port=0
      Incr Kanal                                            'next servo
   End If
End If
If Kanal = 1 Then
   If Servo2 = 0 Then
      Timer1 = Servo(2)
      Servo2 = 1
   Else
      Servo2 = 0
      Incr Kanal
   End If
End If

If Kanal = 2 Then
  Timer1 = 53536                                            'Pause for 16ms
  Kanal = 0
End If
Return

waterirq:
incr tensecond
Timer0=0
If Tensecond > 304 And Waterpresent(2) = 1 Then             '304 = 10s  = 304x32,8ms for 1 timer overflow
   waterpresent(1)=0
   Servo(1) = Smv - 500                                     '2ms bypass valve closed
   Waterlowled=1
   Electricpump=1
End If
Return

Calibration:

DO

INCR LEDtoggle
Analogueinput(1)=Getadc(0)
Analogueinput(2)=Getadc(1)
Analogueinput(3)=Getadc(2)
Analogueinput(4)=Getadc(3)


Pilotflame = Analogueinput(3)/10

Servo(1) = Smv + 500                                        ' 1ms
Servo(2) = Smv - 500                                        '2ms if servo is jittering use another variable to combine these calculations and give out only 1 value
Servo(2)= Servo(2)+Pilotflame

If Ledtoggle > 100 Then                                     'Toggle cycletime depending on time needed for ADC
   IF Calibstate=0 then
      Toggle WaterlowLED
      Toggle GASHIGHLED
      Toggle WaterbypassLED
   End if
   IF Calibstate=<2 then
      WaterlowLED=0
      Toggle GASHIGHLED
      Toggle WaterbypassLED
   End if
   IF Calibstate=<4 then
      WaterlowLED=0
      GASHIGHLED=0
      Toggle WaterbypassLED
   End if
   IF Calibstate=<5 then
      WaterlowLED=0
      GASHIGHLED=0
      WaterbypassLED=0
   End if
End if

'Calibration Boiler sensor
If Sensorcalibswitch=1 and Calibstate=0 then
   Watersensvalue(1) = Analogueinput(1)                     'Measures voltage without water when switch is switched on again
   Calibstate=1
End If
If Sensorcalibswitch=0 and Calibstate=1 then
   Watersensvalue(1) = Watersensvalue(1) + Analogueinput(1) 'Measures voltage with water when switch is switched off again
   Watersensvalue(1) = Watersensvalue(1) / 2
   Eewatersensvalue(1) = Watersensvalue(1)                  'writes average sensor value on EERAM
   Waitms 10
   Calibstate = 2
   Waterlowled = 0
End If

'Calibration feed tank sensor
If Sensorcalibswitch = 1 And Calibstate = 2 Then
   Watersensvalue(2) = Analogueinput(4)                     'Measures voltage without water when switch is switched on again
   Calibstate=3
End If
If Sensorcalibswitch = 0 And Calibstate = 3 Then
   Watersensvalue(2) = Watersensvalue(2) + Analogueinput(4) 'Measures voltage with water when switch is switched off again
   Watersensvalue(2) = Watersensvalue(2) / 2
   Eewatersensvalue(2) = Watersensvalue(2)                  'writes average sensor value on EERAM
   Waitms 10
   Calibstate = 4
   GASHIGHLED=0
End if

If Sensorcalibswitch=1 and Calibstate=2 then
   Calibstate=5
   WaterbypassLED=0
End if

Loop
End
Title: Re: Help writing pic code
Post by: afb on August 07, 2014, 05:41:58 pm
Timebandit - the PICAXE basic code is NOT compiled, it is interpreted - that's why it's slower - I recall it takes about 1mSec per (high level basic) instruction at 4Mhz. The more recent xxM2 chips can be configured to run at 32Mhz.

Megatron - looks like Timebandit is well on the way with his solution, you'd do well to ride on his back! 

Title: Re: Help writing pic code
Post by: Time Bandit on August 07, 2014, 06:48:01 pm
Okay that makes sense, 1ms would probably be still enough for that one here.
BASCOM outputs definetly machine code, thatīs probably the cause why itīs as fast as C-Code.

Title: Re: Help writing pic code
Post by: megatron on August 08, 2014, 02:24:03 pm
Hi Tobias
The feed tank sensor is just a probe so the output will be digital and it won't need calibrating.
Yes both level sensors work on the same servo.
You're right, if both levels low, bypass valve open and LED lit. No effect on gas valve, we still need steam to get boat back.
The gas valve is either fully open or nearly closed (adjusted by pilot flame pot)
The pilot flame is not set during calibration. It is adjusted with pot and continually monitored while program is running.
During calibration the gas servo should be in pilot flame position and the bypass valve in open position (electric pump off)
The calibration switch will be a push button mounted on circuit board either NC or NO.
The pressure sensor does not need calibrating. It will output exactly half supply voltage when pressure correct. If signal greater than half Vs then gas valve open. If signal less than half Vs then gas valve closed to pilot flame. Does Attiny have a voltage comparator on board? If not how sensitive are the inputs for differentiating between a 1 and a 0, this needs to be very tight.
There's no need to switch off after calibration, just go straight to main program.
Control unit and servos will be powered from same battery, I may add a voltage regulator to power control unit.
What size cap would you recommend?

Hello afb
welcome to the discussion.
When I opened this topic I had 2 goals in mind.
Firstly to build a small boiler control unit, and secondly to try and learn how to program pics.
I really appreciate Time Bandit writing the Attiny code and I will probably use it.  I would also like some help trying to convert it to either pic or picaxe code as I think i will learn a lot from doing it.
Any help doing this I would also appreciate very much.

regards
Stew
Title: Re: Help writing pic code
Post by: afb on August 08, 2014, 02:33:16 pm
Hi Stew

I've sent you a PM giving my contacrt details for if and when you need help

Alan Bond
Title: Re: Help writing pic code
Post by: Time Bandit on August 08, 2014, 08:44:08 pm
Stew,
 try to read and understand the code.
I tried to make it understandable.
After your answers it just needs some minor changes.
A few sentences deleted and some things im the setup mode changed.

The switch off after the setup has a reason. The chip likes a controlled complete shutdown to store the eeram correctly. If you e.g. have a short brownout before the shutdown it may be corrupted.
Thats why nearly everybody switches of power after writing on the non volatile memory during program exeution.

At least 47microFarad. The bigger the better  %%
But with a battery it's not so necessary. Low power BEC make the problems.

You should generally overthink what you want to do in the Future.
If it will be sound related or more complex controls e.g. real closed loop controls like a 360 degree schottel control the Picaxe will be too slow.
It's probably fast enough for the ABC but believe me this program is not even using 5% of the capability of the AVR.
For most RC tasks like mixers etc it's enough, but I would make my decision on 2 things and that's if real (internal or external) clocked timers and Interrupts are available on the Picaxe.
If not I wouldnt go for it. Without them none of my more complex progeams would work.

Title: Re: Help writing pic code
Post by: afb on August 09, 2014, 01:26:56 am
Tobias

There's no denying that the AVR is a superior chip, but just for the record the PICAXE does have interrupt capability. For timers you need to choose your chip carefully - for example the 20X2 has a full function hardware timer whereas the 20M2 has a software "time" variable which gives elapsed seconds only but is subject to errors if blocking commands are used (ie commands where the chip has to wait an indeterminate time for a user interaction)

Alan
Title: Re: Help writing pic code
Post by: megatron on August 09, 2014, 08:18:55 pm
Hi everyone
I'm off for a weeks camping in the Lake district, I'll see you all when I get back.
I hope Alan and Tobias don't come to blows before then.
Cheers
Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 05, 2014, 08:15:44 pm
Thought I'd just throw in my comments in case  it might help to hear another persons path into PIC programming. I have built a working cotrol system for a flash-steam boiler. When I started this project I had never heard of a microcontroller before. I bought a Pickit 3 programmer (about Ģ35 when I bought it) a decent bread board (essential), a few PIC chips and downloaded the free and excellent programming suite from Microchip along with data sheets for the PICs. I bought a book on programming but it was not very much use. I find it very useful to work up the programmes as flow charts in powerpoint before writing any code. I've stuck to using assembler and have no plans to move to a higher level language since I can do everything I need and I like the feeling of knowing exactly what is going on and none of the programmes are what you could call very complicated.

In order to show that it is quite possible for a novice (with no electronics skills) to develop PIC circuits directly with unadulterated PIC devices this summarises part of my current system. There are 5 PICS (16F1827) that interact via I2C serial bus. One measures steam temperature using maths routines to convert amplified thermocouple output to degrees C and sends commands to the PIC controlling the fuel pump stepper motor to set its speed etc. Another PIC measures  water pump speed by timing the pulses from a Hall effect sensor on the pump shaft and it also controls the speed of this pump by PWM. Most of the PICs run at 16 MHz. Most of my boards are strip boards and I only ventured into etching a board when it came to the needs for analysing the thermocouple outputs.  It did take a bit or perseverence but I feel it was well worthwhile because of all the possibilities that are now opened up. I have no experience of using PICaxe chips but started looking at them once briefly and decided to go with the straight PICs. I'd be happy to offer advice if you ever decide to use PIC chips - but I'll be no use outside the assembler environment.

Reagrds  Mike
Title: Re: Help writing pic code
Post by: megatron on September 06, 2014, 12:36:51 pm
Hi everyone,
I'm back after a well deserved extended holiday.

I've thought long and hard and decided I want to go down the PIC route using assembler.
It may not be the easiest or best method for this particular project but possibly the best for me and any future projects.

I'd like to welcome TurboTyne to the discussion, I'm sure you could be a big help to me.
I have a copy of PIC IN PRACTICE which takes you through several projects but doesn't explain things very clearly.
Which book did you start with and have you found any good tutorials?
I think I could work out the program side of it but may need help choosing the right PIC and configuring it

Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 06, 2014, 04:53:59 pm
Hi Stew

Happy to help if I can. Of course, there are bound to be other (and better ways) to do most things (i.e. i don't claim to be an expert).   I bought "The PIC microcontroller" by Morton and then picked up a used copy of "PIC in practice" by Smith. This was an ex-library copy (2nd edition) so may be an older edition than your book.

The Microchip website carries a wealth of info in the form of data sheets for each device, application notes with code examples for all sorts of applications and a forum for each broad class of PIC device where you can get advice and search for solutions to problems. This is also the place to download the MPLAB integrated developer environment. Also, I'm pretty sure there is a collection of tutorials on the MP website. Of great importance there are pages that summarise the properties of the large range of PIC devices.

It is a long while since I took my first steps but I think that I started out following some examples in one of those books whereby you write simple code to turn LEDs on and off, flash them and write code to eliminate switch bouncing pulses when using switches to alter binary inputs.  I started using a simple PIC16C54 chip but later wished that I'd used something with a wider range of functions. The 16F54 now sit in a box and will probably never be touched again - but they only cost a few pence each. Trouble is, with a more sophisticated chip there is the risk of info overload when you start out.  I now use 16F1826 or 16F1827and these devices costing a mere couple of quid need a 400 page data sheet to cover (in minimal detail) all their functionalities - that thought always impresses me.

Another key document on the MP site is the PICmicro Mid-Range MCU Family Reference Manual (about 600 pages long) (i.e. for the 16-bit or 16F class of PIC). There are many PICS that are much more sophisticated (18F etc) but 16F devices can do everything (and more) than I will ever need.

I guess you will make a list of the functions you need and then look at the list of features. Trouble is the number just of 16F devices is huge. I you go for a more complex device, you can ignore the features you don't currently require. While many aspects of PIC programming are common to all dvices, much detail is not common and firmware may have to be edited to make it work on a different device.

If the 16F1826/7 chips have all the functions you need, you could do worse than use them. They use the extended instruction set which is an advantage and is one of the reasons why code written for PICs without this feature may need to be alterred before it will run on them.

Sorry for going on so much - I got a bit carried away. If you want to post a list of the features you can envisage needing to use I'll be happy to offer an opinion. i.e. how many analogue and binary inputs, how many plain binary outputs, outputs to servos, PWM etc and any analogue outputs.

Regards

Mike
Title: Re: Help writing pic code
Post by: megatron on September 06, 2014, 05:21:51 pm
Hi Mike
I don't want to run before I can walk so I want to use the simplest pic possible.
If I keep it very basic i think an 8 pin pic should do.
Inputs
pressure sensor; this will output half supply voltage when pressure reaches preset value, possibly analogue depending on how sensitive a/d converter is,(10 bit would be good), otherwise I may need to use external voltage comparator, then digital.
level sensor; if using 5v supply this will output approx 2v or 3v depending on water level. probably digital input.
pilot flame pot; 0 to 5v, analogue input.
calibration switch; on or off, digital input.

Outputs
2 x servo outputs.

I hope that makes sense.
Once I've mastered an 8 pin chip I may move to 14 pin and add some extra features, but that's in the future.

Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 06, 2014, 10:54:00 pm
Hi Stew

I realised I made an error in my previous post - 16F PICs are 8-bit, not 16-bit. (i.e. data is moved around as single bytes).

In response to your outline, I suspect that pin count is not directly related to complexity/ease of use.  The low pin count devices can be very cost-effective in a mass-produced product but might need more skilfully written compact code to fit their often smaller memory and they have no flexibility in pin useage.  Also, if you need an external crystal oscillator to time slow processes, then you use 2 more pins leaving just 4 for i/o functions.  The books I read use the 18-pin PICS in their starting projects. However, I am sure you will gain useful experience from a 8-pin (i.e. 12F) series PIC.

Looks like you are thinking of 2 analogue and two digital inputs plus 2 PWM outputs = 6 pins plus 0V and +5V    = 8 pins.
But that means you would have to use the same pins for programming. Life can be a little simpler if some of the ICSP (i.e. in circuit programming) connections are not used for other purposes.

I am wondering if you already have a pressure sensor. If so, I'd be interested to hear what type it is. I have one I bought a year ago but I still have not set it up. Yes, the PICs I use do have 10-bit A to D converter modules and you can choose to use an additional pin to input a reference voltage instead of comparing to +5V . That would mean yet another pin is needed.

I started following the book using the 18 pin 16F54 and soon migrated upwards to 16F818 and 16F819 (the same but with more memory). Then I needed some extra capability so started using the enhanced type of PIC 16F1826/7 (all 18 pins). With hindsight I wish I'd gone from 16F54 straight to the 16F1826.

Regards

Mike
Title: Re: Help writing pic code
Post by: TurboTyne on September 07, 2014, 06:41:30 am
One additional important reason for having more than the minimum number of pins is that an extra output or 2 to switch on/off LEDs can be invaluable when debugging your code. You insert comands to effect these switching operations at various points in the code to track down where the execution has reached before hitting a problem etc. Similarly an extra digital input to enable you to control code execution can also be invaluable. Remember, you can always ignore extra pins when they are not needed. 

Mike
Title: Re: Help writing pic code
Post by: megatron on September 07, 2014, 08:46:03 am
Hi Mike
I've also made an error, The level sensor will need to be analogue.
The pressure sensor I've made is actually a temperature sensor (thermistor), as temperature increases so does pressure.
The main reason for choosing 8 pin was to make the circuit board design simpler as the enclosure I want to use is quite small.
I suppose I could try to do a layout using a 14 pin chip and see if it would fit. If you've used stripboard before you will appreciate how quickly you run out of holes.
I don't intend to do any in circuit programming and would like a pic with an internal oscillator.
I would also need a small amount of eeprom memory for calibrating the level sensor.

Stew
Title: Re: Help writing pic code
Post by: flashtwo on September 07, 2014, 09:41:28 am
Hi Stew,

I had to make the same decision when looking for a control system for my monotube boiler (see Flash Steam Boiler control thread). I didn't know how to control the boiler and wanted an easily adaptable system that didn't need rebuilding as with a mechanical system, or resoldering with electronics; therefore a PIC based system allowed lots of changes to be made without resorting to the soldering iron.

The servo jittering problem that's been mentioned is typical of pre-written software that works in isolation, but has problems in incorporating with other code. Writing your own code gives you complete control over interfacing with the real world without having to make compromises using other peoples code. I also used Assembler throughtout  - I didn't buy any programing books, I just used Microchips data sheets for the particular PIC being used, plus a bit of internet research.

If you take Mike's approach and gradually work up by switching an LED on/off using a switch, then perhaps a potentiometer giving an analogue input that is limit tested to switch an LED on/off, then using Timers with interrupts doing the same job, you'll be well underway in understanding the system. Don't be put off by interrupts they do a wonderful job - just make sure that the interrupt handler is the first bit of code in your program (but we'll get to the detail when you need further advice).

A couple of DOs  - DO give your code a Version number. Your code will usually be a development of an existing one and, at the top of your code, keep a record of the version number and the reasons for the new version. DO put lots of comments with your code explaining what your are trying to achieve.

Regarding the use of thermistors - I haven't used them for years, but I now understand they are quiet accurate, do they cover the range of boiler temperatures up to 70psi?

Once you've produced some "standard" code you can then use it in other projects.

Ian

Title: Re: Help writing pic code
Post by: TurboTyne on September 07, 2014, 10:08:27 am
Hi Mike
I've also made an error, The level sensor will need to be analogue.
The pressure sensor I've made is actually a temperature sensor (thermistor), as temperature increases so does pressure.
The main reason for choosing 8 pin was to make the circuit board design simpler as the enclosure I want to use is quite small.
I suppose I could try to do a layout using a 14 pin chip and see if it would fit. If you've used stripboard before you will appreciate how quickly you run out of holes.
I don't intend to do any in circuit programming and would like a pic with an internal oscillator.
I would also need a small amount of eeprom memory for calibrating the level sensor.

Stew

Hi Stew

Do you know which programmer you will use? I don't know how much you've read already and I've only ever used ICSP (with a Pickit 3), but, as I understand things, a BIG advantage of ICSP is the ability to very quickly edit the code, re-programme the PIC and test it without repeatedly moving the PIC between programmer and circuit.  This avoids risk of physical and static damge to the PIC and frustration to the user, bearing in mind that you will need to repeat this cycle of edit-programme-test many dozens (hundreds) of times. Obviously I don't know your space restrictions etc but since the physical size of the PIC is an issue, one way forward you could consider is using a larger and more flexible device to learn with and to develop your firmware  - using ICSP. Presumably you'll start out on a breadboard. Then, once things look good, you could try changing to a smaller PIC of the same basic structure, since, by then you will hopefully only need to make minor tweaks to the code to make it compatibe with the new chip. But, once you get into this field I bet you'll realise that you will want to be able to make adjustments to various aspects of the programme. After all, a big advantage of microcontrollers is this very ability to alter the way a system responds without using a soldering iron.

It was Ian's posts that got me into PIC programming and his advice about version numbers is spot on. I do my best to keep things organised but, sadly, I've lost track of the time I've wasted working out which version of firmware I should be using for the next round of editing.

The rewards for mastering this technology are great so don't be put off by that steep learning curve.

Regards
Mike
Title: Re: Help writing pic code
Post by: megatron on September 07, 2014, 01:01:08 pm
Ian, the thermistors I'm using are good for 300degC so can easily cope with the temp in our boilers. They are made by ATC Semitec.

Mike, the programmer I have is a PIC K150, a cheap chinese jobby but it seems to work ok. It has a ZIF socket and I will use a ZIF socket on my prototype board as well.
I have a couple of pic16f627a chips which I could use to get started then as you say port it over to a smaller chip.

Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 08, 2014, 06:22:31 am
Hi Stew

Sounds like a good plan. I hope you'll let us know how you get on. I'll be interested to hear more about your boiler control system.
As Ian said, let us know if you have further questions as and when ....

There is no shortage of web pages about PIC programming out there. I came across this one and mention it here because, in addition to introductory guidance about PIC programming, it also gives links to what seem to be simple home-made programmers / in-circuit programmers. I only looked at this stuff very briefly so have no idea how good it all is.

http://www.markhennessy.co.uk/pic/

Good luck with the PICs,   Mike
Title: Re: Help writing pic code
Post by: megatron on September 14, 2014, 07:53:52 pm
Hi
A question for Mike or Ian.
I have a rough idea of how the program will work but I am short of a couple of pieces of code.

The pic will be running at 8Mhz and I need some code to produce a 1ms delay, that's the easy bit.

I will have a pot connected to 1 of the analogue inputs which will supply from 0 to 5v(supply voltage). I want to use this to produce a delay of 0 to 0.1ms. I don't need 10bit resolution so would I be able to use say the 4 or 5 most significant bits to create a loop? and if so how? The times don't have to be exact, within 2 or 3% would do.

I also need to know how to use a timer to count to 20ms.
The pic I think I'll be using is a pic16f684.

hope you can help
Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 15, 2014, 08:44:11 am
Hi Stew
I'm writing this from android tablet so find it easiest to attach a couple of pdf files.

No doubt others can suggest some cleverer trcks but these suggestions should work.
I hope they make sense.

Regards   Mike
Title: Re: Help writing pic code
Post by: TurboTyne on September 15, 2014, 09:26:29 am
Jusr realised that I was not thinking straight before. Should have said to set AD conversion to give left justified result and then just use the upper byte of the result. I.e. don, t need to use rotate etc.
Mike
Title: Re: Help writing pic code
Post by: megatron on September 15, 2014, 10:24:10 am
Hi Mike
It will take me a little while to get my head around this but am I right in thinking that you are using tmr1 for both these delays? I would like the 2 timings to run independently of each other. e.g.

Start timer-->check pressure-->turn on servo1-->either (1ms delay + 0-0.1ms variable delay) or (1ms delay + 1ms delay)--> turn off servo1-->check boiler level-->turn on servo2-->either (1ms delay) or (1ms delay +1ms delay)-->turn off servo2-->wait until timer = 20ms-->clear timer-->goto start

hope that makes sense.

regards
Stew

P.S. As we live close to each other could we meet up and talk this over with a pint or two. I could show you the system I've already built.
Title: Re: Help writing pic code
Post by: flashtwo on September 15, 2014, 10:56:13 am
Hi Stew,

Based on the PIC 16F 684.

Please tell us if we are “teaching grandma to suck eggs” and there are many solutions to a problem – this is my version.

Have you considered a device frequency (Fosc) of 4MHz (4Mhz crystal).

If you look at the data sheet Figure 5-1, the Timer can use the internal clock which is Fosc/4 which then increments the Timer every microsecond ( 1us) if Fosc is 4Mhz.

Incrementing Timers by 1us becomes very useful when working with the servos, which use the 1 to 2ms PWM signal (i.e. 1000 to 2000us).
When programing, we will be using 3 bases decimal, binary and Hexadecimal – therefore d, b or h after a number stops any confusion.

This solution is to give the potentiometer complete mechanical movement a range of 0 to 0.127ms.

Now, if we want a 0 to 0.1ms delay, we need to load a number between 0 and 100d into the timer (assuming a 4MHz frequency – 1us clock). The Timers actually count up to zero (the overflow condition) and then issue an interrupt to say that they’ve arrived at zero.

Now Timer0 is an 8 bit register, and therefore can represent a number of the range 0 to 255d (it is very useful to have a calculator than can switch between decimal, binary and Hex). Since the Timer counts up to zero, we must initially set it to 155d for a 100us delay (see Paragraph 5.1.1 note about the two instruction delay if we want to be really accurate). You will notice that the Timer is set to the equation “255d minus delay”.

The Timer0 then increments every clock pulse to 255d and then overflows to zero and issues the interrupt.

To reiterate what Mike has said…

The analogue input value, as you can see from Fig. 9.3, arrives at two registers ADRESH and ADRESL containing the highest 8 bits of the analogue value in the first register and the lowest 2 bits in the second register – if ADFM is set to zero.

We just have to “right shift” the register once to get a value of 0 – 127d, which can go into the Timer equation above. Set bit 8 of ADH to zero in case the carry from bit 0 is 1.

First move the value of ADRESH into your own registers, say, ADH. This avoids the possibility of ADRESH changing during your conversion.
Little register sketches appear at this stage!

Now in ADH you have the value to be subtracted from 255d before it sets the Timer.

Referring to the instruction set Table 13.2 – then are plenty of logical operators like “RRF” right rotate and “BTFSS”, which can be used to reduce the 10bit analogue value into a 7 bit value that can be used in the Timer equation.  You can also get your teeth into “SUBWF” for the subtraction process.

I hope this points you in the right direction. It can be a bit (excuse pun!) of a challenge to start with, but each instruction mastered is like adding another spanner to the tool kit!

Ian
Title: Re: Help writing pic code
Post by: megatron on September 15, 2014, 11:53:29 am
Hi Ian

Firstly I am happy to use whichever frequency is best.

A delay of 0-0.127ms would be quite alright.

Am I right in thinking that I would use tmr0 for the variable delay and tmr1 for the 20ms delay?

In summary I would read the value of ADRESH, place it into a user register ADH, rotate right and clear bit7. Subtract this from 255D and use this for the starting point of the timer.

Please note that my head is now spinning a lot faster than 50hz.

regards
Stew
Title: Re: Help writing pic code
Post by: flashtwo on September 15, 2014, 01:19:10 pm
Hi Stew,

I do wonder if we're trying to crack a nut with a sledgehammer.

If you are using this project to understand PICs or other types of modern controllers, then that is fine - it can open up a whole range of uses.

I'm not familiar with the Cheddar ABC unit nor what servo 1 and 2 are doing. Would it be possible for a brief description? - I've looked on the internet but couldn't find anything.

Why did your control box end up much bigger than the Cheddar original? Could different chips/relays be used?

Ian
Title: Re: Help writing pic code
Post by: megatron on September 15, 2014, 02:12:24 pm
Hi Ian
A brief description of the Cheddar ABC.
There are 3 sensors
1; optical sensor to detect water in the sightglass
2; temperature sensor to sense boiler pressure
3; water level sensor to detect water in the feed tank

there are 2 servos
1; operates gas valve
2; operates water bypass valve

The unit is designed to operate with an engine driven water pump. This pump operates continually pumping water to a t-piece. 1 leg of the t-piece connects to the boiler via a non return valve, the other leg of the t-piece connects to a bypass valve. When the bypass valve is open the water is pumped back to the tank. When the bypass valve is closed the water is forced into the boiler.
When the optical sensor sees water in the sightglass the bypass valve is opened, when no water is seen the bypass valve is closed.

The gas is controlled using a double gas valve, this controls the main flow of gas to the burner and also supplies a small amount of gas to allow the flame to burn with a small pilot flame, the pilot flame is adjustable via a screw on the gas valve.
If the temperature of the boiler is below a preset level (adjustable with a pot) the gas valve is opened, if the boiler temperature is above the preset level the valve is closed and the flame is reduced to a pilot flame.

The water in the feed tank is also monitored so that if the water drops below a certain point the water bypass valve is held in the open position and a warning lamp is lit. This prevents the water pump running dry and destroying itself. The gas valve is not affected as you still need steam pressure to get the boat back.

My system uses a single gas valve with the pilot flame being controlled by a pot, hence the need for a variable delay.

The Cheddar system is much smaller than mine because they use a chip similar to a pic to control everything and it is built on a bespoke PCB. Mine was built using only passive components on stripboard. They both give pretty much the same result, but I want to make mine smaller.

Hope that's clear
Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 15, 2014, 06:43:27 pm
Hi Stew
Re: meeting up, yes, I'd like to see your set up - maybe we can arrange something via PM etc.

As Ian has already said, you would need to use 2 timers for this, not just TMR1 and his method of exploiting the interrupt upon roll over of each timer is certainly the way to go. I have never used a servo but your scheme seems ok. to me although as Ian said , using PWM outputs would be an alternative although l think you would need a different PIC with 2 PWM modules.

I assume that the output from your water level gauge is just full on or full off. If so, does the by pass valve get opened and closed very frequently?  I was wondering if there might be a need or possibility of some sort of control that moves the by-pass valve to an intermediate position rather than keep oscillating between full open and full shut.

Final question, how does temperature error adjust gas valve position ? i.e. what computation ?
Regards Mike

Title: Re: Help writing pic code
Post by: flashtwo on September 15, 2014, 06:54:23 pm
Hi Stew,

Thanks for the Cheddar description.

Are the valves operated by servos (requiring PWM) or solenoids (requiring a relay contact), i.e. just open/closed with nothing in between?

Ian.
Title: Re: Help writing pic code
Post by: megatron on September 15, 2014, 07:21:33 pm
Hi Mike
When you ask about the water level sensor I assume you mean the sightglass sensor for the boiler. This sensor gives an output of approx 2v when water present and 3v when no water present, this would need to go to an analogue input and will need calibrating occasionally ( but that's another story). On the system I have built the servo is only operated if there is no water detected for 10 seconds. This is to prevent the servo operating when the water is sloshing about. Again this will have to be implemented somehow, but I was trying to keep the program as simple as possible to begin with. I think it would be very difficult to alter the bypass valve to give exactly the right flow.
The pressure is regulated just like a thermostat, if the voltage from the sensor is below 1/2 supply voltage the gas is turned off and if above the gas is turned on. This needs to be very tight as just a few mV difference will alter the pressure by a couple of psi.
cheers
Stew
Title: Re: Help writing pic code
Post by: megatron on September 15, 2014, 07:25:23 pm
Hi Ian
The valves are operated by servos. The water bypass valve is just open or closed but the gas valve needs to be in either the fully open position or in the pilot flame position where it can be altered with a pot to give a suitable flame.
Stew
Title: Re: Help writing pic code
Post by: flashtwo on September 15, 2014, 08:01:03 pm
Hi Stew,

The pilot flame on my steamer is via a 1/8th inch crimped pipe. The pipe is gently crimped in several places until the desired flame size is achieved. The pipe is drilled in three places so that I have effectively three pilot flames.

The pilot flame is also used to evaporate the liquid propane/butane fuel (I use the gas cylinder inverted to prevent it freezing up) before the gas goes back to the pilot flame and also to the main burner control valve.

If you could use solenoids, it would simplify the electronics a lot by not requiring PWM forming circuits (or software!) and might get away with a quad power op amp chip.

This may simplify your requirement.

Ian
Title: Re: Help writing pic code
Post by: megatron on September 15, 2014, 08:30:51 pm
Hi Ian,

I appreciate what you're saying but as I said at the beginning of this thread I have 2 goals, 1 is to make my unit smaller and the other is to learn how to program pics.
I don't think using a quad op amp would simplify the circuit enough for me to reduce the size significantly as I already use a quad op amp to operate the sensors and even adding a dual would make the circuit too complicated to fit the size of circuit board I want to use.
The beauty of using a pic is that all the terminals can be directly attached to the pic pins and the connections don't have to meander all over the board. There will also be a much smaller parts count using a pic. It is very easy to run out of space when using stripboard, and there always seems to be 1 hole too few.

Stew
Title: Re: Help writing pic code
Post by: flashtwo on September 16, 2014, 10:05:54 am
Hi Stew,

It was worth exploring the options before going down the PIC route, it was precisely what I did and I ended up with a system that could very easily be adapted and, if the new version didn't work, I could reload the previous software in a few minutes.

Once you've got a PIC interfacing with a standard servo, it opens up lots of applications.

Have you decided on which PIC programmer to use? I started with the Maplin's Vellerman  K8048 (Code: N36AC) and have recently moved on to Microchips PICKit 2 Starter Kit (from Rapid Electronics) because my new computer only has USB connections. The Starter Kit comes with a PIC16F690 which has the timers and analogue inputs.

Full steam ahead now for a PIC ABC that has more potential than the original!

Ian

Title: Re: Help writing pic code
Post by: megatron on September 16, 2014, 10:48:18 am
Hi Ian,

I originally bought a pic k150, a cheap chinese programmer, which I have used to burn a few example progs. However i spotted a genuine picKit 2 on ebay which was going for a song so I had to buy it, should be here in the next couple of days.
I've also ordered a couple of pic16f684 chips.
I've found a bit of code which gives a 1ms delay and I should be able to alter it to give my variable delay.
What I need now is 2 timers, 1 to count to 20ms and the other somewhere between 5 and 10 seconds.
Which timer would be best for each of these?

Stew
Title: Re: Help writing pic code
Post by: boneash on September 16, 2014, 10:59:41 am
have just seen this one on ebay, any good?
Title: Re: Help writing pic code
Post by: boneash on September 16, 2014, 11:00:54 am
Have just seen this one ........
 
eBay item number:
281440864725
Title: Re: Help writing pic code
Post by: megatron on September 16, 2014, 11:13:00 am
Hi boneash
that's a bargain but look at the sellers feedback score, I'd be wary.
Stew
Title: Re: Help writing pic code
Post by: Time Bandit on September 16, 2014, 09:43:16 pm

What I need now is 2 timers, 1 to count to 20ms and the other somewhere between 5 and 10 seconds.
Which timer would be best for each of these?

Stew
I have no idea about the PIC you are using, but I would do it this way:
Iīd use only 1 timer for everything including the servo signal, it works better if you use a 16 bit timer for that to get a better resolution of the 1-2ms servo signal.

1. overflow:
Set the timer to 1-2ms until overflow with a variable that features the servo value you want to have + set output port to 1
Increment another variableX if variableX< 250 (=5s), if variableX > 250 do whatever you want to do, best is just to set another variableY from 0 to 1 and do the rest in the main program to keep the ISR short + set variableX to 0 again.
Next overflow:
set output port to 0 + set timer to 18ms until overflow (if timer overflows too fast set it to 9ms + another overflow with 9ms)

with this you just need 1 timer for all functions you just need another variable to check of 1. overflow should happen or next overflow.
Title: Re: Help writing pic code
Post by: TurboTyne on September 16, 2014, 10:35:17 pm
Hi Stew
There will be many strategies but here is another suggestion. Your PIC has 3 timers. TMR0 and TMR1 run off of the instruction clock. These are 8 bit timers so they can count up to 256 . TMR1 is a 16 bit timer and so can count up to 65, 536. This timer van run from the instruction clock or from am external oscillator such as a 32 KHz crystal.

However, TMR0 and TMR2 have what are called prescalers which means that they can effectively also count up to 65, 536.
Assuming you run the PIC at 4MHz like Ian suggested, so each instruction cycle is 1 usec, then each of these timers can reach a max time of 65.5 msecs.  That means you could use TMR1 to set a time period of between 1 msec and 2 msec to control the pulse widths to be sent in turn to each servo. TMR0 could be used to set the 20 msec delay that determines when you restart the servo control cycle. To get the 10 sec period you could then do what Time Bandit suggests and decrement a register that is initially set at 50 and when this reaches zero you reset it to 50 and decrement another register initially set at 10 (for a 10 sec delay).
If I've understood things correctly one of the servo pulse times will be set  at l msec plus a time depending of whether bypass valve should be open or closed. Then the other pulse width will equal 1 msec plus a short time calculated from one of the A D inputs plus a time dependent on whether the gas valve is open or almost closed.

Regard  Mike
Title: Re: Help writing pic code
Post by: megatron on September 16, 2014, 10:36:28 pm
Hi Tobias
The chip I am going to use has 3 timers, 2 8bit and 1 16bit.
I have some code which gives a 1ms delay which I can use for the servo positions. I need 1 of the timers to count to 20ms so that the program repeats every 20ms. I also need a timer which will stop the water servo operating until the water level has been low for approx 5seconds. The rest of the program still has to operate during this time.
I have no idea how to do all this with 1 timer
Stew
Title: Re: Help writing pic code
Post by: megatron on September 16, 2014, 10:56:46 pm
Hi Mike

TMR1 also has a 3bit prescaler so it can count to 524288. Is it possible to count how many times it overflows, say 10 times. This delay isn't critical, anything between 5 and 10 seconds would do.
The gas servo will be either closed:- 1ms + delay for pilot flame. or open:- 2ms
The water servo will be either closed:- 1ms. or open:- 2ms

Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 17, 2014, 07:42:40 am
Hi Stew
Yes, that should work O.K. However, using that method would mean you would have to use the third timer to generate the 20 msec timing periods.

 If you use TMR1 to time the pulse width then l would set its prescaler to 1:8. This will give a sufficient maximum timing period ( 2.048 msecs) whilst giving maximum time resolution. Although you don't need high timing resolution to open and close the valves, l guess it could be important for setting the pilot position. But decrementing a register and carrying out a new task when it reaches zero is dead simple -using decfsz command.

Regarding how to achieve all this, l find it very useful to draw a flow diagram with operation boxes and branch points etc. Initially operation boxes can describe complex operations which get broken down into actual PIC commands later.
Regards   Mike
Title: Re: Help writing pic code
Post by: megatron on September 17, 2014, 10:41:19 am
Hi Mike
If I use TMR0 with a prescaler of 256 and count to 78 this will give a time of 19.968ms, close enough for what I need.
And if I allow it to loop 250 times, that will give me a delay of approx 5 seconds, again close enough for what I need.
I have some code to give a 1ms delay which I can also alter and use to give the pilot flame delay(If I use the 5 most significant bits of the analogue output of the pot I can get 11.5 degrees of servo movement with a 5bit resolution, should be good enough).
All I need to do now is put all this into some sort of order, configure the ports etc. and I should be good to go.

any comments
Stew
Title: Re: Help writing pic code
Post by: megatron on September 17, 2014, 11:51:35 am
Hi Ian
My PICkit 2 arrived this morning with no cables or software.
I have managed to find a couple of cables but would like to know which software I need. Could you tell me what software you use and version numbers so that I can install the same and we're both singing from the same songsheet.
Stew
Title: Re: Help writing pic code
Post by: megatron on September 17, 2014, 04:17:16 pm
WOW
2 new toys in 1 day.
Just received a lovely shiny analogue oscilloscope.
Gone to play.
Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 17, 2014, 06:14:16 pm
Hi Mike
If I use TMR0 with a prescaler of 256 and count to 78 this will give a time of 19.968ms, close enough for what I need.
And if I allow it to loop 250 times, that will give me a delay of approx 5 seconds, again close enough for what I need.
I have some code to give a 1ms delay which I can also alter and use to give the pilot flame delay(If I use the 5 most significant bits of the analogue output of the pot I can get 11.5 degrees of servo movement with a 5bit resolution, should be good enough).
All I need to do now is put all this into some sort of order, configure the ports etc. and I should be good to go.

any comments
Stew

Hi Stew
Sounds like you have a workable plan.
How does your code generate the delay periods?

Re 'scopes, I've found my basic Picoscope was very useful for checking PWM outputs and absolutely invaluable for getting to the bottom of some weird problems with serial communication between PICs. Hope you enjoy yours.
Regards   Mike
Title: Re: Help writing pic code
Post by: Time Bandit on September 17, 2014, 06:26:21 pm
Itīs always good to use the resources economically since if the programs get more complex you dont want to use 2 timers just for the servo output.
Use a 16 bit timer with prescaler 8 @ 8Mhz clock speed (values change at 4Mhz)

So Timervalue for 1ms = 64535
2ms= 63535
1000 points resolution, no Servo can use this  :} (at 4Mhz 500 points)
Timervalue for the 17ms (2 servos at average 1,5ms) break between pulses = 48535
The ISR will look like this (V are variables with any name):


ISR:
If V1=1 then set Timer 1 to 65535-V2 (servovalue for servo 1 between 1000 and 2000) / set servoouputpin1 = 1
If V1=2 then set servooutputpin1=0 / set Timer 1 to 65535-V3 (servovalue for servo 2 between 1000 and 2000)/ set servoouputpin2 = 1
If V3=3 then set servooutputpin2=0 / set Timer 1 to 48535 (17ms break) / increment V4 if  water below level / if V4>249 set V5=1 (use V5 in main program to react on water low level) / if water lvl good set V4=0 V5=0

Increment V1 until V1=4 else set V1=1
return
Title: Re: Help writing pic code
Post by: megatron on September 17, 2014, 07:01:08 pm
Hi Mike
This is the code for the 1ms delay

Wait1ms   movlw    d'250'       ;Initial value - tweak if req.
              nop
loop1ms   addlw    d'255'       ;dec W
              btfss    STATUS, Z    ;Zero flag set?
              goto     loop1ms      ;  No, keep looping
              return                ;  Yes, 1ms done

If I substitute the 5bit analogue value of the pot for the '250' in the first line it will give me the pilot flame delay.
I haven't worked out the code for the 20ms loop yet but everything will be nested inside it so that the program loops every 20ms irrespective of the delay for the servos.

Stew
Title: Re: Help writing pic code
Post by: flashtwo on September 17, 2014, 07:44:01 pm
Hi Stew,

This piece of code solved a lot of strange problems when I first started, it was one of the very few occasions that I resorted to searching the Web for a solution. Place it at the very start of your code. The memory of the 684 is only over one "page", so it is not a problem, but with larger PICs the memory may split over several pages and when you leave one page, due to an interrupt,  you have to make a note of where you have come from so you can return after servicing the interrupt. See Section 2.0 of the Data Sheet.

Notice the use of "H" to define the following number as an Hexadecimal address. I tend to enter the Instructions e.g.  ORG, GOTO etc, in upper case because they don't get confused with the comments after the semi-colon which are in lower case - that's just my style.

      ORG     H'0000'      ;Reset vector address. This is where the PIC starts after a physical Reset, i.e. pin 4 has been decked to Ground. See Data Sheet 12.3d.
      GOTO  RESET      ;goto RESET routine when boot. The RESET routine is the main body of the code after the Interrupt Service Routine.
      ORG   H'0004'      ; Interrupt vector address. All interrupts arrive at this physical address H'0004'
      NOP                 ; No operation.
                                 ; BEWARE!!! you must avoid the "GOTO INTERRUPT" or "GOTO ISR" statement at the interrupt vector as this inherits the
                                 ; page bits from the page that's interrupted! Just put a NOP at the interrupt vector
                                 ; and drop through to an interrupt routine in Page 0 at address physical address  h'0005'.
                                 ; From: http://www.piclist.org/techref/microchip/pages.htm

                                                Place your Interrupt Service Routine (ISR) from this location onwards and before the RESET routine.

;          **********************************
;              **  RESET :  main boot routine  **
;              **********************************

RESET   Your code starts here

What a lot to absorb!

Ian.


Title: Re: Help writing pic code
Post by: flashtwo on September 17, 2014, 08:02:04 pm
Hi Stew,

I originally wrote the code in Notepad on my old computer and compiled it using MPASM v5.51 and then used the Vellerman board to download to the PIC in circuit.

I only got the more up to date PicKit 2 because the old Vellerman board didn't support a USB connection that is on my new computer. I haven't used the new PicKit 2 other than proving that it worked OK. My current monotube boiler controller's software is fairly mature now and I haven't any changes to make at the moment.

The versions I've currently got are:-

PicKit 2 version 2.50.02,   MPLAB IDE version 8.70

Ian
Title: Re: Help writing pic code
Post by: TurboTyne on September 17, 2014, 08:20:26 pm
Hi Stew
That seems neat but I guess the nop should be in the loop rather than just before it so as to give 4 instruction clock cycles per loop.
Of course the disadvantage of relying heavily on this type of delay is that the PIC cannot do anything else while it's waiting but obviously that does not matter in this situation.
It will be a great step forwards to mimick the Cheddar control system but as control systems go this is very basic. To pick up on one of Ian's comments, once you have a PIC control working you can consider all sorts of improvements without turning on the soldering iron. If you look at Ian's thread on flash steam plant control you'see much discussion of other control systems that you could think about. Trouble is you could end up like me and get sidetracked with making valves and controls but never get anything actually finished  {-)
Regards   Mike
Title: Re: Help writing pic code
Post by: megatron on September 17, 2014, 08:41:03 pm
Hi Mike
I copied that code from page six of the Mark Hennessy web site that you showed me. He explains the code and how long it takes. He also seems to think the NOP does not need to be there at all.

Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 17, 2014, 09:08:57 pm
Ah yes, I overlooked the fact that btfss can take 2 cycles.  {:-{
Mike
Title: Re: Help writing pic code
Post by: megatron on September 18, 2014, 12:44:12 am
Hi Ian
I've installed PICkit v2.61 and built a programmer board and everything seems to work. I also downloaded mplabX but that seems very complicated. I'll try an earlier version.
Mike
Do you use mplab and if so which version?

Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 18, 2014, 06:56:02 am
Hi Stew
Yes I do use MPLAB. I'm away from home at present and cannot remember the exact version but it is the latest of the versions that preceed the X version. I have been planning to switch to X at some point as I guess this will get best support from MP in the future, but I've not tried it yet. I think all versions may look a bit challenging when you start out but like many things, its not as bad as it first looks.
I really like the simulator tool. It lets you look at all the various registers as you step through your code.
If you downloaded yours from the MPweb site you'll already realise that the various versions are all available.

Regards  Mike
Title: Re: Help writing pic code
Post by: megatron on September 19, 2014, 11:27:08 am
For my 20ms loop using timer0 with a prescaler of 256, how do I know when TMR0 = 78?

Stew
Title: Re: Help writing pic code
Post by: megatron on September 19, 2014, 01:37:10 pm
I'm off to zap a few million brain cells at York beer festival.
See you all in a couple of days.
Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 19, 2014, 02:48:49 pm
For my 20ms loop using timer0 with a prescaler of 256, how do I know when TMR0 = 78?

Stew

Hi Stew

Follow guidelines posted by Ian already. The following waffle expands a little upon what Ian said:

Since you have pre-scaler set at 256 (i.e. by setting bits in the OPTION register), the timer increments every time the instruction cycle (1 usec) goes through 256 cycles i.e. once every 256 usecs. The TMR0 register can be read and written to. If you clear it before starting the timer, it starts counting up from zero. It is a 1 byte timer, so when it reaches value 255 it cannot go any higher and rolls over to zero and immediately re-starts the process. When it rolls over it causes the interrupt flag TOIF in the INTCON register to be set. If you don't have interrupts enabled this will not do anything and the only way to respond to it is by keep testing the flag bit to see when it gets set. Once that happens you must clear the flag and then do what you want to do. However, the best way is to enable interrupts and set up an interrupt service routine (ISR) which would also need to clear the interrupt flag and then carry out the response you want. This way the PIC can get on with other tasks but when the interrupt occurs its current processes are halted temporarily while it reponds in the way specified in the ISR.
In order to time for ca 20 msec you need to stop the TMR0, move a starting value into TMR0 register and then re-start the timer. The starting value is 256 - 78 = 178. This means that when the timer has counted from 178 to 255 + 1 (i.e. 78 * 256 usecs) it will roll over to zero and trigger the IF flag to be set.

Enjoy the beers s s s!!

Mike
Title: Re: Help writing pic code
Post by: megatron on September 21, 2014, 02:15:35 pm
Hi Mike
Thanks for advice.
I'll try making a simple loop that turns a servo either right or left depending on a switch being pressed. This will test the timings.
I don't think I'll need to use an interrupt as the loop will be waiting for the time to reach 20ms, I'll simply keep testing the interrupt flag.
I'll also be able to alter this loop as I add a second servo and use the sensors as inputs. Should be plain sailing from there.
regards
Stew
Title: Re: Help writing pic code
Post by: megatron on September 21, 2014, 06:57:16 pm
Can you see any problems with this code

;CONFIGURATION SECTION

START    MOVLW    B'00011111'    ;5bits of PORTA are I/P
        MOVWF    TRISA

        MOVLW    B'00000000'               
        MOVWF    TRISB        ;PORTB is OUTPUT

        MOVLW    B'00000111'    ;Prescaler is /256
        MOVWF    OPTION_REG

        CLRF    PORTA        ;Clears PortA.
        CLRF    PORTB        ;Clears PortB.

;SUBROUTINE SECTION.

WAIT1MS   MOVLW    d'250'       ;Initial value - tweak if req.
          NOP
LOOP1MS   ADDLW    d'255'       ;dec W
          BTFSS    STATUS, Z    ;Zero flag set?
          GOTO     LOOP1MS      ;  No, keep looping
          RETURN                ;  Yes, 1ms done



;Program starts now.

BEGIN
    CLRF    TMR0    ;clears tmr0
    CLRW        ;clears working register
    ADDLW    177    ;256-177=78
    ADDWF    TMR0    ;counts for 20ms
    BCF    INTCON,2    ;clear overflow flag
    BCF    OPTION_REG,5    ;start timer mode
    BTFSS    PORTA,0        ;test for switch press
    GOTO    SERVOR
    GOTO    SERVOL
SERVOR    BSF    PORTB,0        ;turn on power to servo
CALL    WAIT1MS           
    BCF    PORTB,0        ;turn off power to servo
    GOTO    WAIT20MS   
SERVOL    BSF    PORTB,0        ;turn on power to servo
    CALL    WAIT1MS       
    CALL    WAIT1MS       
    BCF    PORTB,0        ;turn off power to servo
    GOTO    WAIT20MS   
WAIT20MS
    BTFSS    INTCON,2    ;wait until timer0 reaches 20ms   
    GOTO    WAIT20MS
    BSF    OPTION_REG,5    ;stop timer mode
    GOTO    BEGIN        ;keep looping
END

Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 21, 2014, 08:52:43 pm
Can you see any problems with this code

 
Stew

Hi Stew

I assume this is just the meat of your prohramme? i.e. do you have

    list      p=16F????    ; list directive to define processor
    #include <P16F????.inc>        ; processor specific variable definitions

also do you have a

    __CONFIG

statement to define clock source etc?
and staements to set clock fequency.

I always include the following which suppresses trivial error messages:

    errorlevel  -302              ; suppress message 302 from list file


Minor point but instead of         
        MOVLW    B'00000000'               
        MOVWF    TRISB        ;PORTB is OUTPUT
you could just write 
       CLRF         TRISB

Instead of
  CLRW        ;clears working register
    ADDLW    177    ;256-177=78
    ADDWF    TMR0    ;counts for 20ms

I would just write:

MOVLW    d'177'
MOVWF   TMR0

When reading in values as literals you must always indicate the type of value (i.e. decimal, hex, binary)
Also you want to move the value into TMR0 not add anything together.

I don't know what PORTB pin 0 is connected to. Maybe an LED via a resistor? I don't see how it would influence a servo.

Testing for switch presses can be problematic but maybe not in this case. It is common to include code to stop detecting switch bounce.

One final thing, as a precaution it is common to include BANKSEL directives. I don't know if this is necessary for your PIC but I've wasted ages tracing bugs which turn out to be omitted BANKSELs at unfortunate points in the programme. If all the registers you are using are in the same bank you can forget this for the time being.

I've had a quick look but have not checked the details of which bits are relevant in INTCON etc. I hope these comments are helpful (and also that they are accurate  %) ).

Mike
Title: Re: Help writing pic code
Post by: megatron on September 21, 2014, 10:25:36 pm
Hi Mike
I've added a few lines and made the alterations you suggest, it now looks like the following.

; EQUATES SECTION

TMR0        EQU    1        ;means TMR0 is file 1.   
STATUS        EQU    3        ;means STATUS is file 3.   
PORTA        EQU    5        ;means PORTA  is file 5.   
PORTC        EQU    7        ;means PORTB is file 6.
INTCON        EQU    08H        ;INTCON is file 08H
TRISA        EQU    85H     ;TRISA (the PORTA I/O selection) is file 85H
TRISC        EQU    87H     ;TRISC (the PORTC I/O selection) is file 86H
OPTION_REG     EQU    81H        ;the OPTION register is file 81H   
ZEROBIT        EQU    2        ;means ZEROBIT is bit 2.   
;*********************************************************

    LIST    P=16F684    ; we are using the 16F684.
    ORG    0                ; the start address in memory is 0
    GOTO    START        ; goto start!

;**********************************************************************
; Configuration Bits


;*********************************************************


;CONFIGURATION SECTION

START   
    MOVLW    B'00011111'    ;5bits of PORTA are I/P
**MOVWF    TRISA
**CLRF    TRISC        ;PORTC is OUTPUT
    MOVLW    B'00000111'    ;Prescaler is /256
**MOVWF    OPTION_REG
    CLRF    PORTA        ;Clears PortA.
    CLRF    PORTC        ;Clears PortC.

;SUBROUTINE SECTION.

WAIT1MS   MOVLW    d'250'       ;Initial value - tweak if req.
          NOP
LOOP1MS   ADDLW    d'255'       ;dec W
          BTFSS    STATUS,2            ;Zero flag set?
          GOTO     LOOP1MS      ;  No, keep looping
          RETURN                ;  Yes, 1ms done



;Program starts now.

BEGIN
    CLRF    TMR0    ;clears tmr0
    MOVLW    d'178'    ;256-178=78 counts for 20ms
    MOVWF    TMR0   
    BCF    INTCON,2    ;clear overflow flag
**BCF    OPTION_REG,5    ;start timer mode
    BTFSS    PORTA,0        ;test for switch press
    GOTO    SERVOR
    GOTO    SERVOL
SERVOR    BSF    PORTC,0        ;turn on power to servo
    CALL    WAIT1MS           
    BCF    PORTC,0        ;turn off power to servo
    GOTO    WAIT20MS   
SERVOL    BSF    PORTC,0        ;turn on power to servo
    CALL    WAIT1MS       
    CALL    WAIT1MS       
    BCF    PORTC,0        ;turn off power to servo
    GOTO    WAIT20MS   
WAIT20MS
    BTFSS    INTCON,2    ;wait until timer0 reaches 20ms   
    GOTO    WAIT20MS
**BSF    OPTION_REG,5    ;stop timer mode
    GOTO    BEGIN        ;keep looping
    END

When I try to do a quickbuild I get the following message.


Clean: Deleting intermediary and output files.
Clean: Done.
Executing: "C:\Program Files\Microchip\MPASM Suite\MPASMWIN.exe" /q /p16F684 "20msloop.asm" /l"20msloop.lst" /e"20msloop.err"
Message[302] C:\PIC PROJECTS\20MSLOOP\20MSLOOP.ASM 29 : Register in operand not in bank 0.  Ensure that bank bits are correct.
Message[302] C:\PIC PROJECTS\20MSLOOP\20MSLOOP.ASM 30 : Register in operand not in bank 0.  Ensure that bank bits are correct.
Message[302] C:\PIC PROJECTS\20MSLOOP\20MSLOOP.ASM 32 : Register in operand not in bank 0.  Ensure that bank bits are correct.
Message[302] C:\PIC PROJECTS\20MSLOOP\20MSLOOP.ASM 54 : Register in operand not in bank 0.  Ensure that bank bits are correct.
Message[302] C:\PIC PROJECTS\20MSLOOP\20MSLOOP.ASM 70 : Register in operand not in bank 0.  Ensure that bank bits are correct.
Executing: "C:\Program Files\Microchip\MPASM Suite\mplink.exe" /p16F684 "20msloop.o" /z__MPLAB_BUILD=1 /o"20msloop.cof" /M"20msloop.map" /W /x


error lines are as follows

29    MOVWF    TRISA
30    CLRF    TRISC
32    MOVWF    OPTION_REG
54    BCF    OPTION_REG,5    ;start timer mode
70    BSF    OPTION_REG,5    ;stop timer mode

I've marked them with asterix


I have looked at how to change banks but can't get my head around it.
Also for some reason this chip uses PortA and PortC not PortB.
I have seen programs with an include statement but have no idea what they are.
I'll try to figure out how to do the __config statement.

PortC,0 will be connected to the signal wire of the servo, I think it just needs a tiny current.

Stew
Title: Re: Help writing pic code
Post by: flashtwo on September 21, 2014, 11:09:36 pm
Hi Stew,

Before you use a Register the PIC needs to know which memory bank it is located by setting the STATUS word. All is fine until you wish to use another register in the other memory bank, in which case you have to switch banks by resetting the STATUS word, otherwise the PIC will just refer to the wrong register.

From the 684 documentation Fig 2-2 you can see that the Special Function Registers (the ones that control the functions like Timers and I/O etc.) and General Purpose Registers (the ones that you control and give names to) are spread between the two Memory Banks.

To switch between the two banks, one must set bits in the STATUS word, which appears in both banks. Not being in the correct bank causes the most numerous bugs in a program and needs a bit of discipline to avoid. To simplify switching between banks, I place routines at the start of the code which can be called avoiding repetition of the switching code, viz:

BANK_0_P0   BCF   STATUS,RP0   ; Switch to register bank 0.
              BCF   STATUS,RP1   ;      
              RETURN

BANK_1_P0   BSF   STATUS,RP0   ; Switch to register bank 1.
              BCF   STATUS,RP1   ;      
              RETURN

BANK_2_P0   BCF   STATUS,RP0   ; Switch to register bank 2.
              BSF   STATUS,RP1   ;      
              RETURN

BANK_3_P0   BSF   STATUS,RP0   ; Switch to register bank 3.
              BSF   STATUS,RP1   ;      
              RETURN

On the larger PICs there are four banks, so I have shown routines for all four.

I know the 684 has only one memory page, but for larger PICs the routines have to be repeated on each page and have a routine name dedicated to that page; hence my routines for page zero are called "BANK_0_P0", "BANK_1_P0" etc.

Part of the programers art is to group the variables (registers) that are used together in the same memory bank to avoid lots of confusing switching.

Ian
Title: Re: Help writing pic code
Post by: TurboTyne on September 21, 2014, 11:10:55 pm
Hi Stew

You should be able to find in the files provided by MP that come with the MPLAB IDE a file that is a typical programme file for the PIC16F684 device. This is called PIC16F684.temp. Included in it are all the routine setting up stuff that can be really tricky to work out from scratch. Also there will be a file called PIC16F684.INC. This contains definitions of all the special function registers so there is no need to use EQU directives to define registers such as TMR0 and PORTA.

I am using MPLAB IDE v8.92. The INC files were in the directory "MPASM suite" and TEWMP files in the directory "MPASM suite\template\code". If you can't find the files in your library then let me know and I'll send them off thread.

Mike
Title: Re: Help writing pic code
Post by: megatron on September 21, 2014, 11:45:21 pm
Hi Mike
I've tried putting my code into the template and including the .inc file but I get the same errors as before.

    list        p=16f684        ; list directive to define processor
    #include    <P16F684.inc>        ; processor specific variable definitions
   
    __CONFIG    _CP_OFF & _CPD_OFF & _BOD_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_ON & _FCMEN_OFF & _IESO_OFF


; '__CONFIG' directive is used to embed configuration data within .asm file.
; The labels following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.






;***** VARIABLE DEFINITIONS
w_temp        EQU    0x7E            ; variable used for context saving
status_temp    EQU    0x7F            ; variable used for context saving





;**********************************************************************
    ORG        0x000            ; processor reset vector
      goto        main            ; go to beginning of program


    ORG        0x004            ; interrupt vector location
    movwf        w_temp            ; save off current W register contents
    movf        STATUS,w        ; move status register into W register
    movwf        status_temp        ; save off contents of STATUS register

; isr code can go here or be located as a call subroutine elsewhere

    movf        status_temp,w        ; retrieve copy of STATUS register
    movwf        STATUS            ; restore pre-isr STATUS register contents
    swapf        w_temp,f
    swapf        w_temp,w        ; restore pre-isr W register contents
    retfie                    ; return from interrupt


main


START   
    MOVLW    B'00011111'    ;5bits of PORTA are I/P
    MOVWF    TRISA
    CLRF    TRISC        ;PORTC is OUTPUT
    MOVLW    B'00000111'    ;Prescaler is /256
    MOVWF    OPTION_REG
    CLRF    PORTA        ;Clears PortA.
    CLRF    PORTC        ;Clears PortC.

;SUBROUTINE SECTION.

WAIT1MS   MOVLW    d'250'       ;Initial value - tweak if req.
          NOP
LOOP1MS   ADDLW    d'255'       ;dec W
          BTFSS    STATUS,2  ;Zero flag set?
          GOTO     LOOP1MS      ;  No, keep looping
          RETURN                ;  Yes, 1ms done



;Program starts now.

BEGIN
    CLRF    TMR0    ;clears tmr0
    MOVLW    d'178'    ;256-178=78 counts for 20ms
    MOVWF    TMR0   
    BCF    INTCON,2    ;clear overflow flag
    BCF    OPTION_REG,5    ;start timer mode
    BTFSS    PORTA,0        ;test for switch press
    GOTO    SERVOR
    GOTO    SERVOL
SERVOR    BSF    PORTC,0        ;turn on power to servo
    CALL    WAIT1MS           
    BCF    PORTC,0        ;turn off power to servo
    GOTO    WAIT20MS   
SERVOL    BSF    PORTC,0        ;turn on power to servo
    CALL    WAIT1MS       
    CALL    WAIT1MS       
    BCF    PORTC,0        ;turn off power to servo
    GOTO    WAIT20MS   
WAIT20MS
    BTFSS    INTCON,2    ;wait until timer0 reaches 20ms   
    GOTO    WAIT20MS
    BSF    OPTION_REG,5    ;stop timer mode
    GOTO    BEGIN        ;keep looping




    ORG    0x2100                ; data EEPROM location
    DE    1,2,3,4                ; define first four EEPROM locations as 1,2,3,&4




    END                       ; directive 'end of program'
Title: Re: Help writing pic code
Post by: megatron on September 22, 2014, 12:08:00 am
Hi
This is getting more confusing by the minute.
Can someone please tell me what code I need to put in and where.
Maybe then I can work out what is going on.
I've looked for banksel and can't find any mention of it in the datasheet or the mplab user guide.
Thanks
Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 22, 2014, 07:06:49 am
Hi Stew

Another important document you need to download from here:

http://www.microchip.com/pagehandler/en-us/family/mplabx/home.html

Scroll down to documentation section and get:

MPASM/MPLINK users guide

This explains about BANKSEL etc.


You can either do it Ian's way or use BANKSEL but you must do something because your error messages are saying the bank is wrong.

Simplest thing to do is, before each and every instruction that refers to any register place a line like this example:

e.g. instead of: 

    CLRF    TMR0    ;clears tmr0
    MOVLW    d'178'    ;256-178=78 counts for 20ms
    MOVWF    TMR0   
    BCF    INTCON,2    ;clear overflow flag
**BCF    OPTION_REG,5    ;start timer mode
    BTFSS    PORTA,0        ;test for switch press


you should write:

    BANKSEL      TMR0
    CLRF    TMR0    ;clears tmr0
    MOVLW    d'178'    ;256-178=78 counts for 20ms
    MOVWF    TMR0   
    BANKSEL    INTCON
    BCF    INTCON,2    ;clear overflow flag
    BANKSEL    OPTION
**BCF    OPTION_REG,5    ;start timer mode
    BANKSEL  PORTA
    BTFSS    PORTA,0        ;test for switch press



BANKSEL instructs the compiler to insert extra commands to make the PIC read from the correct memory bank for the register in question. i.e. it inserts lines equivalent to the one's suggested by Ian.


If you know that the next register to be used is in the same bank as the last you can omit the BANKSEL, but it is safest to always use it, especially when starting out. Downside of extra BANKSELs is that you end up inserting unnecessary code, but for short programmes like yours this does not matter.

Regards  Mike

Title: Re: Help writing pic code
Post by: flashtwo on September 22, 2014, 09:11:29 am
Hi Stew,

Regarding the _CONFIG file, I forgo any #include statements and set it up from scratch. It encourages a complete understanding of what is happening and removes the "mystery" and "magic" of using other peoples code. The only document I refer to is the PIC's data sheet and derive all my code from there. This is RAW programing, but it enables understandable code and removes unnecessary library code.

The _CONFIG is only a register with lots of "switches" that sets up the basic operation of the PIC; here is my version for an 16F877 PIC:-

;==========================================================================
;
;       Configuration Bits
;
;==========================================================================

_BODEN_ON                    EQU     H'3FFF'
_BODEN_OFF                   EQU     H'3FBF'
_CP_ALL                      EQU     H'03FF'
_CP_75                       EQU     H'17FF'
_CP_50                       EQU     H'2BFF'
_CP_OFF                      EQU     H'3FFF'
_DATA_CP_ON                  EQU     H'3EFF'
_DATA_CP_OFF                 EQU     H'3FFF'
_PWRTE_OFF                   EQU     H'3FFF'
_PWRTE_ON                    EQU     H'3FF7'
_WDT_ON                      EQU     H'3FFF'
_WDT_OFF                     EQU     H'3FFB'
_LVP_ON                      EQU     H'3FFF'
_LVP_OFF                     EQU     H'3F7F'
_MCLRE_ON                    EQU     H'3FFF'
_MCLRE_OFF                   EQU     H'3FDF'
_ER_OSC_CLKOUT               EQU     H'3FFF'
_ER_OSC_NOCLKOUT             EQU     H'3FFE'
_INTRC_OSC_CLKOUT            EQU     H'3FFD'
_INTRC_OSC_NOCLKOUT          EQU     H'3FFC'
_EXTCLK_OSC                  EQU     H'3FEF'
_LP_OSC                      EQU     H'3FEC'
_XT_OSC                      EQU     H'3FFD'
_HS_OSC                      EQU     H'3FEE'

   __CONFIG        _BODEN_ON & _CP_OFF & _DATA_CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF  & _XT_OSC

(the Tabbing doesn't seem to transfer - sorry)

Ian
Title: Re: Help writing pic code
Post by: megatron on September 22, 2014, 12:11:54 pm
Hi Mike & Ian
At the moment I feel like I am searching down blind alleys and I don't even know what I am searching for. Unfortunately the more information I'm given the more blind alleys I'm searching down.
Would it be possible for one of you to turn the following code into working code.
I feel I would learn quicker if I had some working code to try and understand rather than code that doesn't work which is battering my brain.
This code seems to build ok and it seems to run ok in MPLAB SIM, although very slowly, but when I burn it to a chip I'm not getting any output.

; EQUATES SECTION

TMR0        EQU        1        ;means TMR0 is file 1.   
STATUS      EQU        3        ;means STATUS is file 3.   
PORTA       EQU        5        ;means PORTA  is file 5.   
PORTC       EQU        7        ;means PORTB is file 6.
INTCON      EQU        08H        ;INTCON is file 08H
TRISA       EQU        85H     ;TRISA (the PORTA I/O selection) is file 85H
TRISC       EQU        87H     ;TRISC (the PORTC I/O selection) is file 86H
OPTION_REG  EQU        81H        ;the OPTION register is file 81H   
ZEROBIT     EQU        2        ;means ZEROBIT is bit 2.   
OSCCON        EQU        8FH
;*********************************************************

    LIST    P=16F684    ; we are using the 16F684.
    ORG        0                ; the start address in memory is 0
    GOTO    START        ; goto start!

;**********************************************************************
; Configuration Bits
    __CONFIG    H'34C4'

;*********************************************************
;SUBROUTINE SECTION.

WAIT1MS   MOVLW    d'250'       ;Initial value - tweak if req.
          NOP
LOOP1MS   ADDLW    d'255'       ;dec W
          BTFSS    STATUS,2            ;Zero flag set?
          GOTO    LOOP1MS      ;  No, keep looping
          RETURN                ;  Yes, 1ms done


;CONFIGURATION SECTION

START   
    BANKSEL    TRISA   
    MOVLW   B'00011111'    ;5bits of PORTA are I/P
    MOVWF   TRISA
    CLRF    TRISC        ;PORTC is OUTPUT
    MOVLW   B'00000111'    ;Prescaler is /256
    MOVWF   OPTION_REG
    MOVLW    B'01100111'
    MOVWF    OSCCON   
    BANKSEL    PORTA
    CLRF    PORTA        ;Clears PortA.
    CLRF    PORTC        ;Clears PortC.




;Program starts now.

BEGIN
        CLRF    TMR0    ;clears tmr0
        MOVLW    d'178'    ;256-178=78 counts for 20ms
        MOVWF    TMR0   
        BCF        INTCON,2    ;clear overflow flag
        BANKSEL    OPTION_REG
        BCF        OPTION_REG,5    ;start timer mode
        BANKSEL    PORTA
        BTFSS    PORTA,0        ;test for switch press
        GOTO    SERVOR
        GOTO    SERVOL
SERVOR  BSF        PORTC,0        ;turn on power to servo
        CALL    WAIT1MS           
        BCF        PORTC,0        ;turn off power to servo
        GOTO    WAIT20MS   
SERVOL  BSF        PORTC,0        ;turn on power to servo
        CALL    WAIT1MS       
        CALL    WAIT1MS       
        BCF        PORTC,0        ;turn off power to servo
        GOTO    WAIT20MS   
WAIT20MS
        BTFSS    INTCON,2    ;wait until timer0 reaches 20ms   
        GOTO    WAIT20MS
        BANKSEL    OPTION_REG
        BSF        OPTION_REG,5    ;stop timer mode
        BANKSEL    TMR0
        GOTO    BEGIN        ;keep looping
        END
Title: Re: Help writing pic code
Post by: flashtwo on September 22, 2014, 01:53:42 pm
Hi Stew,

We're working on it.

I'm finding it a useful revision course.

Tenacious is the best software tool!

Ian.
Title: Re: Help writing pic code
Post by: megatron on September 22, 2014, 02:13:05 pm
Thanks a lot Ian
I thought climbing Skiddaw was steep but not half as steep as the learning curve here.
My brain hurts.
Stew
Title: Re: Help writing pic code
Post by: flashtwo on September 22, 2014, 02:52:31 pm
Hi Stew,

Initial thought regards the "EQU" statement.

Looking at document DS33014L-page 68, the number format is either H'3' or 0x003, hexadecimal being the default "radix".

E.g. STATUS   EQU  H'3' or STATUS   EQU  0x003,  personally I prefer the H'3' version.

How did you arrive at the config H'34C4', which suggests to me that you are using an external clock source?

Ian

Ian
Title: Re: Help writing pic code
Post by: flashtwo on September 22, 2014, 03:04:15 pm
Hi Stew,

Try putting the ORG after the __Config , viz:-

      ORG           H'0000'      ;Reset vector address.
      GOTO   START             ;goto START routine on bootup.
      ORG           H'0004'      ; Interrupt vector address.
      NOP         ; No operation.
                 place your Interrupt Service routine here (if used)

               END of the interrupt service routine

               your routines
               START

Ian
Title: Re: Help writing pic code
Post by: megatron on September 22, 2014, 04:19:21 pm
Hi Ian
I used mplab to set the config bits and that's the result it gave me.

FOSC   internal oscillator, I/O on rc4 and RA5
WDTE  watchdog timer disabled
PWRTE  power up timer enabled
CP       code protection disabled
CPD     data code protection disabled
BOREN  brown out detect disabled
IESO     internal external switchover mode enabled
FCMEN  fail safe clock monitor disabled



What is ORG, there's no mention of it in datasheet?
Please try and keep this as simple as possible.
I don't think this is a complicated bit of code, it should be easy to sort out.

Stew
Title: Re: Help writing pic code
Post by: megatron on September 22, 2014, 04:29:12 pm
Ian
I added the ORG lines and when I tried to build it got the following error

Error[118] C:\PICPROJECTS\20MSLOOP\TEST.ASM 24:Overwriting previous address contents(0000)

Line 24 is GOTO START

Stew
Title: Re: Help writing pic code
Post by: flashtwo on September 22, 2014, 04:58:43 pm
Hi Stew,

The ORG is describe (in somewhat cryptic language!) in the MPASM programmer document DS33014L (page 141) and is the memory location 000h where the PIC starts from when it is RESET (i.e. switched on or manually reset). After 000h, there are three memory locations (before the Interrupt Vector) where some instructions can be placed to handle the RESET, in our case GOTO START.

To put it simply, it is the first in-tray you see when the office lights are switched on and contains the first order of the day - GOTO.

It may be as well to have the most simple cyclic program to start with:

START     NOP
              GOTO START

and see if the system clock is working by putting the 'scope on Pin 3 CLKOUT and looking for a square wave - RA4 will have to be designated as an output. If the clock is not there then __CONFIG may need some attention.

Regarding Error[118] - could you post the code again?

I shall be looking at config again - hang on there!

Ian
Title: Re: Help writing pic code
Post by: megatron on September 22, 2014, 05:23:16 pm
Ian
The code has changed that much I don't know where I am.

Can we start from the beginning ie what do I need to put in the equates section?
Originally it looked like this. Is this correct or do I need to change it?

; EQUATES SECTION

TMR0         EQU        1        ;means TMR0 is file 1.   
STATUS      EQU        3        ;means STATUS is file 3.   
PORTA       EQU        5        ;means PORTA  is file 5.   
PORTC       EQU        7        ;means PORTB is file 6.
INTCON     EQU        08H        ;INTCON is file 08H
TRISA        EQU        85H     ;TRISA (the PORTA I/O selection) is file 85H
TRISC        EQU        87H     ;TRISC (the PORTC I/O selection) is file 86H
OPTION_REG  EQU        81H        ;the OPTION register is file 81H   
ZEROBIT     EQU        2        ;means ZEROBIT is bit 2.   
OSCCON        EQU        8FH
Title: Re: Help writing pic code
Post by: flashtwo on September 22, 2014, 06:32:50 pm
Hi Stew,

I think the register number after EQU should be of the form H'3' etc., to ensure the programmer (MPASM) knows it is dealing with an hexadecimal number.

To be pedantic, your files should really be referred to as the registers; it avoids future confusion.

My mistake regarding the config number - I was looking at the wrong PIC data sheet.

Regarding the use of a 'scope on pin 3, the config number would have to change the FOSC to INTOSC rather than INTOSCIO and that will allow the CLKOUT to be monitored. The config number will then change from H'34C4' to H'34C5'.

Regarding getting lost with all the changes, always copy your code into a new version number and make the changes in the copy and keep the old code (it may be better than the new one!). At the top of the code page, put your version comments in and your reasons and objectives for change, plus the date - example:-

;*  CONTROLLER_V32 copy of CONTROLLER_V31.               *
;*      The feed pump Master is now manually selectable from the Display*
;*      Unit instead of swopping over the ESC connectors and the RPM   *
;*      connectors.                     *
;*      Placed PORTC,ACTIVE in CONTROL routine to give a better      *
;*      oscilloscope square wave.               *
;*      The "A" and "B" Pump displacements are now amendable from the    *
;*      Display Unit.                     *
;*                              *
;*  MODIFIED BY: I GERRARD     23/03/2012               *

Excuse the flying stars, tabbing not consistent.

Have you got two ORG statements that could be causing that error message?

Ian

Title: Re: Help writing pic code
Post by: megatron on September 22, 2014, 08:12:29 pm
Progress

The following code gives me a lovely 5v 1ms pulse every 2ms.
It's not a lot but at least it's something to work from, and it tells me the pic and config is ok.
The problem seems to be in the 20ms delay routine.

; EQUATES SECTION

TMR0         EQU        H'01'        ;means TMR0 is file 1.   
STATUS      EQU        H'03'        ;means STATUS is file 3.   
PORTA       EQU        H'05'        ;means PORTA  is file 5.   
PORTC       EQU        H'07'        ;means PORTB is file 6.
INTCON     EQU        H'08'        ;INTCON is file 08H
TRISA        EQU        H'85'        ;TRISA (the PORTA I/O selection) is file 85H
TRISC        EQU        H'87'        ;TRISC (the PORTC I/O selection) is file 86H
OPTION_REG  EQU   H'81'        ;the OPTION register is file 81H   
ZEROBIT     EQU       H'02'        ;means ZEROBIT is bit 2.   

;*********************************************************

    LIST    P=16F684    ; we are using the 16F684.
    ORG        0                ; the start address in memory is 0
    GOTO    START        ; goto start!

;**********************************************************************
; Configuration Bits
    __CONFIG    H'30C4'

;*********************************************************
;SUBROUTINE SECTION.

WAIT1MS   MOVLW    d'250'       ;Initial value - tweak if req.
                  NOP
LOOP1MS   ADDLW    d'255'       ;dec W
                  BTFSS    STATUS,2            ;Zero flag set?
                  GOTO    LOOP1MS      ;  No, keep looping
                  RETURN                ;  Yes, 1ms done


;CONFIGURATION SECTION

START   
    BANKSEL    TRISA   
    MOVLW   B'00011111'    ;5bits of PORTA are I/P
    MOVWF   TRISA
    CLRF    TRISC        ;PORTC is OUTPUT
    MOVLW   B'00000111'    ;Prescaler is /256
    MOVWF   OPTION_REG
       
    BANKSEL    PORTA
    CLRF    PORTA        ;Clears PortA.
    CLRF    PORTC        ;Clears PortC.




;Program starts now.

BEGIN
    BSF        PORTC,0
    CALL    WAIT1MS
    BCF        PORTC,0
    CALL    WAIT1MS
    GOTO    BEGIN
    END



Happier now
Stew
Title: Re: Help writing pic code
Post by: flashtwo on September 22, 2014, 10:03:55 pm
Hi Stew,

Congratulations!

The learning curve has gone from the vertical to leaning towards the horizontal!

What made it start to work? Was it the EQU values being defined in Hexadecimal or the change in the config from H'34C4' to H'30C4' i.e. the IESO being disabled.

Ian
Title: Re: Help writing pic code
Post by: megatron on September 22, 2014, 10:12:28 pm
Hi Ian
I'm not sure, I changed them and removed the 20ms loop at the same time.
I'll have another play tomorrow and try to figure out what is going on.
Cheers
Stew
Title: Re: Help writing pic code
Post by: flashtwo on September 23, 2014, 12:04:20 am
Hi Stew,

I was intrigued with your WAIT1MS routine and have just realised that you are adding the 2's compliment of 255d, i.e. -1d, to do the decrement 250 times and then executing 4 instructions in the LOOP1MS to give 4us. Thus, 250d x 4 = 1000us = 1ms.

Ian
Title: Re: Help writing pic code
Post by: megatron on September 23, 2014, 07:40:39 am
Hi Ian
I'm afraid I can't take any credit for it. I borrowed the routine from the Mark Hennessy website given to me by Mike.
Cheers
Stew
Title: Re: Help writing pic code
Post by: flashtwo on September 23, 2014, 08:16:52 am
Hi Stew,

This is the stage where connecting an LED to one of the outputs can help in finding any bugs in the code (680ohm in series with LED).

The LED can be switched on (BSF) at the start and then move the switch off (BCF) instruction to parts of the code where there may be a problem - its like playing "Battleships"!

Ian
Title: Re: Help writing pic code
Post by: megatron on September 23, 2014, 10:00:21 am
Hi Ian

I'll take the advice of adding LEDs at various places.
I found an error in the equates section, I had the wrong address for INTCON.

The next stage is to put the 1ms delay into a 10ms loop using TMR0. I'm going to use 2 x 10ms loops instead of a 20ms loop, that way both servos will be inside their own loop and be totally independent.

Stew
Title: Re: Help writing pic code
Post by: megatron on September 23, 2014, 02:26:05 pm
we're flying now

the following code gives a beautiful 1ms pulse every 20ms.
Just need to add some inputs and we're home and dry.

; EQUATES SECTION

TMR0        EQU        H'01'    ;means TMR0 is file 1.   
STATUS      EQU        H'03'    ;means STATUS is file 3.   
PORTA       EQU        H'05'    ;means PORTA  is file 5.   
PORTC       EQU        H'07'    ;means PORTB is file 7.
INTCON      EQU        H'0B'    ;INTCON is file 0BH
TRISA       EQU        H'85'    ;TRISA (the PORTA I/O selection) is file 85H
TRISC       EQU        H'87'    ;TRISC (the PORTC I/O selection) is file 87H
OPTION_REG  EQU        H'81'    ;the OPTION register is file 81H   
ZEROBIT     EQU        H'02'    ;means ZEROBIT is bit 2.   

;*********************************************************

    LIST    P=16F684    ; we are using the 16F684.
    ORG        0            ; the start address in memory is 0
    GOTO    START        ; goto start!

;**********************************************************************
; Configuration Bits
    __CONFIG    H'30C4'

;*********************************************************
; SUBROUTINE SECTION.

WAIT1MS       
    MOVLW    d'250'        ;Initial value - tweak if req.
    NOP
LOOP1MS   
    ADDLW    d'255'        ;dec W
    BTFSS    STATUS,2    ;Zero flag set?
    GOTO    LOOP1MS        ;No, keep looping
    RETURN                ;Yes, 1ms done


; CONFIGURATION SECTION

START   
    BANKSEL    TRISA   
    MOVLW   B'00011111'    ;5bits of PORTA are I/P
    MOVWF   TRISA
    CLRF    TRISC        ;PORTC is OUTPUT
    BANKSEL    PORTA
    CLRF    PORTA        ;Clears PortA.
    CLRF    PORTC        ;Clears PortC.
   



; Program starts now.

BEGIN
    MOVLW    d'217'        ;256-217=39 LOOPS
    MOVWF    TMR0   
    BANKSEL    OPTION_REG
    MOVLW   B'00000111'    ;Prescaler is /256
    MOVWF   OPTION_REG
    BANKSEL    PORTC
    BSF        PORTC,0
    CALL    WAIT1MS
    BCF        PORTC,0

WAIT10MS
    BTFSS    INTCON,2    ;wait until timer0 reaches 10ms   
    GOTO    WAIT10MS
    BCF        INTCON,2
    GOTO    BEGIN2        ;next loop

BEGIN2
    MOVLW    d'217'        ;256-217=39 LOOPS
    MOVWF    TMR0   
    BANKSEL    OPTION_REG
    MOVLW   B'00000111'    ;Prescaler is /256
    MOVWF   OPTION_REG
    BANKSEL    PORTC
   
WAIT10MS2
    BTFSS    INTCON,2    ;wait until timer0 reaches 10ms   
    GOTO    WAIT10MS2
    BCF        INTCON,2
    GOTO    BEGIN        ;keep looping
   
    END

Cheers
Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 23, 2014, 02:44:43 pm
Hi Stew

That's great - well done!

I've been checking the messages in this thread but have not had anything to add over what Ian has been saying.

Now you have a PIC that is doing something I am sure you will soon start thinking of numerous tweaks etc.
Isn't it a great feeling when it works!

Like Ian, I do much of my de-bugging with LEDs attached to one or two pins. I have a few small subroutines that turn the leds on or off or flash them. By moving calls to these subroutines around the code it is easy to track where the programme is going before it hits the problem one is trying to solve.

Regards

Mike
Title: Re: Help writing pic code
Post by: megatron on September 23, 2014, 03:12:02 pm
Hi Mike
Yes I found using an LED very helpful, unfortunately when I first connected it I forgot the resistor and I've blown 4 of the I/O ports on the chip. Fortunately the others still work.
Like you say it is a great feeling when things work.
cheers
Stew
Title: Re: Help writing pic code
Post by: megatron on September 24, 2014, 11:41:11 am
Hi
I've managed eventually to get a servo to move right or left with the push of a button.
It seems that I didn't fry the i/o ports after all, nobody mentioned the CMCON0 or ANSEL registers.
These little chips will be the death of me.
cheers
Stew
Title: Re: Help writing pic code
Post by: TurboTyne on September 24, 2014, 01:28:26 pm
Ah, Ian said your learning curve was no longer vertical, he didn't say it was horizontal  ok2

Glad you've not blown those outputs but that possibility reminds me of a major problem I encountered a few months back.

I use serial communications between several PICs whereby a pin on each can TX or RX data pulses to the equivalent pin on the other PICs. It took me over a week of testing, using the scope and eventually reverting to simple code and LED outputs / switched inputs. What I concluded was that the ability of the data pin on each of 3 PICs to sense the input had been blown but the output function was still working. I think I inadvertently connected a 12V power wire to the wire that connects all the data pins together. The fact that output was working on the same pin that input had failed really confused me. I had to replace 3 PICs! - luckily the other PICs were not connected at the time. I'll be more careful in future (I hope). 

Mike



Title: Re: Help writing pic code
Post by: flashtwo on September 24, 2014, 01:36:06 pm
Hi Stew,

Congratulations, once again! It sounds like you are well underway now, progressing through all the available features.

It was fortuitous that you didn't burn out the I/O.

Addictive isn't it!

Ian
Title: Re: Help writing pic code
Post by: megatron on September 24, 2014, 01:50:37 pm
Hi Mike

I've already blown 1 chip, I use a variable power supply and when I moved it onto my bench I managed to turn the voltage up to 20v. There was no question about if I had damaged the chip, you could see through it.

Yes Ian it is addictive, it's good to get the grey matter working again.

Next task is to make the servo move using a pot, any pointers in advance would be most appreciated.

cheers
Stew
Title: Re: Help writing pic code
Post by: flashtwo on September 24, 2014, 03:05:38 pm
Hi Stew,

This is where I used the 2 byte Timer 1 (TMR1), since it has the resolution to give you the range of in excess of 2000.

Configure it to count at the Internal clock rate of 1 microsecond (1us) and initialise its registers with H'F8' into the high byte and H'2F' into the low byte - this is 63535 in decimal. When you start the clock it will count up to 65535d (H'FFFF'), roll-over to zero and issue an interrupt (sorry) 2000us (2ms) later.

If you set a digital output when you start the clock and reset the output when you receive the interrupt, it will give you a 2ms pulse. This will be within the 20ms code to give a pulse every 20ms.

Now to get 1ms pulse, the timer is initialised with 64535d in it registers and the interrupt will occur after the 1ms.

As you can see, the smaller the value you initialise the Timer with, the longer the pulse width.

The 10 bit analogue input will give you a value from zero to 1023 (that's very convenient!), so if you SUBTRACT that value from 64535 it will give you a pulse range from 2023 to 1000us- voila!

As might appreciate the numbers 64535 and 63545 are not cast in concrete and may be changed to give the servo a greater range than the usual 90deg movement by applying pulses say, from 0.7ms to 2.5ms. This can be very useful if the mechanical link between the servo and, say, the gas valve does not shut the valve completely at the normal 1 or 2ms settings (depends on your mechanical arrangement - my valve is nominally shut at 2ms). If the valve is not shut at 2ms the servo may need to be presented with a 2.1ms pulse (for example).

To get the most benefit from this, you might in the near future consider using a 4MHz crystal as the system clock - it will give you the better accuracy and stability especially when you are trying to adjust the pilot flame. For the moment the internal clock is good enough.

Now you need to practice subtracting two 2-byte numbers.

If you feel that a lower resolution will do (1:255 resolution), then the single byte timers could be used, its just the pilot light I'm thinking of.

Ian
Title: Re: Help writing pic code
Post by: flashtwo on September 24, 2014, 03:45:24 pm
Hi Stew,

If you don't want to do subtractions, you could always just use additions, viz:

Timer setting =  pot value (0-1023) + "2ms" value.

The 2ms value could be nominally 63535d and adjustable.

Ian

Title: Re: Help writing pic code
Post by: megatron on September 24, 2014, 05:05:27 pm
Hi Ian
That's a good idea if I want a high resolution.
I was thinking of using the 8 bits in ADRESH and simply substituting them for the "250" in the wait 1ms routine. Just to test the theory.

I was also thinking that for the pilot flame adjustment I could use the 5 most significant bits of ADRESH instead of the "250" which would give 11.5deg movement over 32 steps which may be good enough.

thoughts
Stew
Title: Re: Help writing pic code
Post by: flashtwo on September 24, 2014, 05:36:38 pm
Hi Stew,

My gas valve, which has a 40TPI thread on the valve stem going to a simple conical plug seat, is driven by the servo via dog-tooth coupling. The range is nominally 1000 (open) to 2000us (closed) and I increment/decrement the completely shut position by steps of 10us, though the rest of the proportional control range moves in 1us steps.

One 10us step is enough to just open the valve for a very small flame. If I try to over-close I can hear the servo stalling.

I think a 0.5% resolution is desirable, but it all depends on the valve design.

250 steps would give you 0.4% resolution, although each step would represent 8us for a range of 2000us.

I think your method stands a good chance of working - give it bash - you can always download a different version, which is the beauty of PICs.

What's your gas valve arrangement?

Ian


Title: Re: Help writing pic code
Post by: megatron on September 24, 2014, 10:55:03 pm
Hi Ian
At the moment I am using a Cheddar ABC gas valve which has the pilot flame adjustment built in.
My current units have been used with standard off the peg servo gas valves but they are analogue hence infinitely variable.
Hopefully this will work but like you say if it doesn't I can easily change the software.

Stew
Title: Re: Help writing pic code
Post by: megatron on September 26, 2014, 09:42:20 am
Hi

For the pilot flame adjustment I am going to use a pot with 2 legs connected to supply voltage and ground with the wiper connected to input pin. The datasheet recommends a maximum impedance of 10K but doesn't say what is ideal. Has anyone used a pot in this situation and what values did you find worked well?
For the boiler pressure input this is basically a voltage divider with two resistances of 15k, not ideal I know, but that's what I'm stuck with. My question is how do I calculate the acquisition time?
I've seen the formula in equation 9-1 page 72 of the datasheet but that's beyond rocket science. Would a 1ms delay be enough?
The curve is heading back to the vertical.

cheers
Stew
Title: Re: Help writing pic code
Post by: flashtwo on September 26, 2014, 10:50:34 am
Hi Stew,

As it says in section 9.3, the A/D convertor has a 5pF capacitor (Fig. 9.4) that has to be charged up and the source resistance Rs controls its charging rate.

In our case the voltage signal is slowly changing compared with, say, an audio input, so that the capacitor will follow our analogue input.

I think you can easily get away with the 15k circuit.

For my boiler application, I calculated (back in the mists of time) the acquisition time of approximately 20us, so, in my code I've allowed a 50us delay between setting ADCON0 for Fosc/32 clock, channel number etc., and starting the A/D conversion AD_GO.

I'd follow the example in 9.2.6 with Fosc/32 and 50us waits.  I used waits and not interrupts, I can't remember why.

Ian
Title: Re: Help writing pic code
Post by: megatron on October 03, 2014, 06:16:06 pm
Hi All
Well after much head scratching I have now got it so that the servo moves left and right with the push of a button, and the right hand position adjustable with a pot.
There is however a small problem. If the voltage to the analogue input drops below about 170mV the servo starts glitching, and if the voltage drops below 140mV the servo shoots off and gives maximum left hand rotation.
I have tried various delays for the acquisition from 0 to 1ms but this makes no difference. I can remedy this by keeping the voltage above 170mV but I was wondering why this happens.
Below is the code for my delays

; SUBROUTINE SECTION.

SAMPLETIME
    MOVLW    d'20'        ;initial value - tweak if required
LOOPST
    ADDLW    d'255'        ;dec W
    BTFSS    STATUS,2    ;zero flag set?
    GOTO    LOOPST        ;no, keep looping
    RETURN                ;yes, sampletime done

PILOT
    BANKSEL    ADCON1
    MOVLW    B'00010000'    ;adc frc clock
    MOVWF    ADCON1
    MOVLW    B'00000100'
    MOVWF    ANSEL        ;an2 set to analogue
    BANKSEL    ADCON0
    MOVLW    B'00001001'    ;left justify,vdd ref,an2,on
    MOVWF    ADCON0
    ;CALL    WAIT1MS
    ;CALL    SAMPLETIME
    BSF    ADCON0,1
    BTFSC    ADCON0,1
    GOTO    $-1
    BCF    STATUS,0    ; use 5 most
    RRF    ADRESH,1    ; significant
    BCF    STATUS,0    ; bits of
    RRF    ADRESH,1    ; adresh
    BCF    STATUS,0    ; to give 5 bit
    RRF    ADRESH,1    ; resolution
    BCF    STATUS,0    ;
    MOVF    ADRESH,W    ;
LOOPP
    BSF    PORTA,0
    ADDLW    d'255'        ;dec W
    BTFSS    STATUS,2    ;zero flag set?
    GOTO    LOOPP        ;no, keep looping
    RETURN            ;yes pilot delay done

WAIT1MS       
    MOVLW    d'250'        ;Initial value - tweak if req.
    NOP
LOOP1MS   
    ADDLW    d'255'        ;dec W
    BTFSS    STATUS,2    ;Zero flag set?
    GOTO    LOOP1MS        ;No, keep looping
    RETURN            ;Yes, 1ms done

Cheers
Stew
Title: Re: Help writing pic code
Post by: flashtwo on October 03, 2014, 06:50:29 pm
Hi Stew,

Good to see that you are progressing, even with a few glitches.

Just a quick thought -

5 bit resolution gives you 1 part in 32.

5 volts divided by 32 gives you 156mV.

Have you looked at the PWM with the 'scope?

I will delve deeper.

Ian.
Title: Re: Help writing pic code
Post by: megatron on October 03, 2014, 06:59:49 pm
Hi Ian
I haven't had a chance to get the scope out yet.
I wonder if the voltage is going so low that the ADCON0,1 bit is never getting cleared.
Stew
Title: Re: Help writing pic code
Post by: TurboTyne on October 03, 2014, 07:02:26 pm
Hi Stew

Yes, I was going to make a similar comment to Ians re: the 5 bit resolution. I am thinking that, as your input voltage drops to about 170 mV the upper 5 bits from the ADC will equal a mix of values of zero and 1 as random noise takes the result above or below the cut-off for detection on each ADC event. Does this cause the glitches? As the voltage drops lower, the result will be consistent zeros. So I am wondering - how do you use the value from the ADC? Can your programme deal with a zero value ? 

Regards  Mike
Title: Re: Help writing pic code
Post by: megatron on October 03, 2014, 07:12:56 pm
Hi Mike
The analogue input is dealt with by the PILOT subroutine and it looks like a 0v input would give me about a 1ms rather than a 0ms delay, however the servo is going further than this as it's hitting the stops.
I'll put the scope on tomorrow when I finish work.
Cheers
Stew
Title: Re: Help writing pic code
Post by: flashtwo on October 03, 2014, 07:18:23 pm
Hi Stew,

There may be a roll-over from zero to 255 in the LOOPP. It may be worth examining the logic in detail of 2's compliment decrementing, i.e.  ADDLW    d'255'        ;dec W

The other method of decrementing is to use the DECFSZ instruction - decrement f, skip if zero.

Ian
Title: Re: Help writing pic code
Post by: TurboTyne on October 03, 2014, 08:00:59 pm
Ah yes, of course - I'd not focussed properly on the end stages.
O.K., I think you need to test the ADC result for zero before you do the first addition of 255. If zero then exit before entering the loop OR if zero then increment it to value 1.
At prersent, if the W register is zero, you then add 255 to give a result that is 255. This then gives the max delay before your timing is complete.
The 2's complement maths works since the value 255 is -1 in 2's complement. But, the PIC does not realise this and just thinks it is the value 255.

Regards  Mike
Title: Re: Help writing pic code
Post by: flashtwo on October 04, 2014, 06:48:52 am
Hi Stew,

This is similar to the old "divide by zero" problem - you have to check the extreme cases which screw up the logic.

One little tip for ease of code reading is to assign (EQU statement) to the register bit numbers,  e.g. STATUS,2 becomes STATUS,ZERO. It saves referring back to the data sheet, viz:-

;----- STATUS Bits --------------------------------------------------------
IRP                     EQU     H'7'
RP1                     EQU     H'6'
RP0                     EQU     H'5'
NOT_TO              EQU     H'4'
NOT_PD                  EQU     H'3'
ZERO                     EQU     H'2'
DC                      EQU     H'1'
CARRY                  EQU     H'0'

or what ever description helps.

No, I haven't got insomnia - we've just collected our daughter from Gatwick Airport!

Ian
Title: Re: Help writing pic code
Post by: flashtwo on October 04, 2014, 07:02:27 am
Hi Stew,

A method of testing for ZERO is to move a register into itself since it affects the STATUS zero flag - see instruction MOVF.

E.G.

                MOVF    DELAY,1                           ; Move DELAY into itself then test for zero.
                BTFSS   STATUS,ZERO                       ; Test STATUS for zero.

Ian
Title: Re: Help writing pic code
Post by: megatron on October 05, 2014, 09:30:19 am
Hi
The problem was indeed caused by the analogue input being zero, now sorted.
Ian, you mentioned the analogue converter using a cap, does each analogue channel have their own cap or is one shared by all of them? The reason I am asking is that I now have to add another analogue input and the acquisition time might become a factor.
Cheers
Stew
Title: Re: Help writing pic code
Post by: flashtwo on October 05, 2014, 01:32:53 pm
Hi Stew,

Glad you sorted the "zero" problem - bet you're getting into the swing of re-programing the PIC.

The hold capacitor seems to be shared by all inputs, since its after the select switch SS (Fig 9.4).

Looking at my code, I select the channel, set the A/D convertor on, wait 50us for acquisition, start the A/D conversion and then go off and process the rest of the code (in my large program it may take 0.1s).

Coming back through the start of the analogue code section, I check to see if the analogue conversion is complete, if so, then I transfer the ADRESH/L into my variable (Temp, Pressure etc.) and then finally change the channel select bits (CHS) for the next analogue channel and then repeat the cycle.

So, for four analogue inputs to update in my code, it takes 0.4s which is more than adequate for the slow moving inputs.

I use the 16F877 PIC and I've noticed the input source resistance maximum value is only 2.5kohm much lower than the 10k of the 684 and I've never had any problems with 10k pots as the inputs.

Ian


Title: Re: Help writing pic code
Post by: megatron on October 07, 2014, 07:08:54 pm
Hi
Well we're half way there, the boiler pressure side of things is now all sorted.
Next is the turn of the water level. This should be fairly straight forward except that I will have to store a calibration value in eeprom. I've read the datasheet several times but it's just not clicking, anyone got any tips on how to store and read data in eeprom?
cheers
Stew
Title: Re: Help writing pic code
Post by: TurboTyne on October 07, 2014, 10:55:00 pm
 Hi Stew


I have code that stores a set of about 20 values in dataEEPROM. It is ages since I looked at this but below is an edited version of my write and read subroutines. I read and write the data from/to a series of registers so I have simply indicated a silly name for single registers in this example.  The process is tricky because you have to go through a sequence of events and then wait for the write process to complete.  First thing is to tell the device which EEPROM location you want to write to / read from. In my case this is the value stored in 'byte_count'.


This is on a PIC16F8127. I looked very quickly and the control registers for dataEEPROM in your PIC seem the same.
Maybe best to have a look at this stuff and come back with further questions.

Good luck.
Mike



write_byte
                BANKSEL                    byte_count

                 movf                          byte_count, W                 BANKSEL                   EEADRL
                movwf                       EEADRL                               ; place current value of byte_count into EE address reg.
                movf                          value_to_be_stored, W
                BANKSEL                    EEDATL
                movwf                        EEDATL                                ; copy data at current register to EEDATL
 
                bcf                                          EECON1, CFGS                                      ; select programme & data space
                bcf                                          EECON1, EEPGD                                    ; select data
                bsf                                          EECON1, WREN                                    ; enable writes
 
                bcf                                          INTCON, GIE                                         ; disable interrupts
                movlw                                  55h
                movwf                                  EECON2
                movlw                                  0AAh
                movwf                                  EECON2
                bsf                                       EECON1, WR                                                               ; start write operation
                bsf                                       INTCON, GIE                                                                 ; enable interrupts
                bcf                                        EECON1, WREN                                                           ; disable writes
                BTFSC                                    EECON1, WR                                      ; wait for any current write operation to complete.
                goto                                       $-2
 
                  return 
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 read_byte
                BANKSEL              byte_count
                movf                     byte_count, W
                BANKSEL              EEADRL
                movwf                  EEADRL                                                 ; place current value of byte_count into EE address reg.
 
                bcf                          EECON1, CFGS                                   ; select programme & data space
                bcf                          EECON1, EEPGD                                 ; select data
                bsf                          EECON1, RD                                        ; start EEread
                movf                       EEDATL, W
               BANKSEL                 register_to_be_written

                movwf                    register_to_be_written                      ; move latest data byte into relevant register.
                 return
Title: Re: Help writing pic code
Post by: flashtwo on October 08, 2014, 09:13:22 am
Hi Mike,

I had a lot of trouble getting the EEPROM write routine to work reliably with multiple writes.

I used the 16F877 PIC and followed the data sheet example where the WR flag is tested at the beginning of the routine to check that any previous writes were completed before any additional writes were attempted. I couldn't get that to reliably work, so, I tried using EEPROM's write complete interrupt with no success.

Finally, I placed a 4ms delay at the end of each write and it worked reliably. The delay didn't impinge on the normal code running since it was only used for manual settings (of two bytes each) which were changed as necessary.

I should have perhaps attempted putting the "WR" bit test at the end of the WRITE routine as in your code.

Ian
Title: Re: Help writing pic code
Post by: megatron on October 08, 2014, 10:35:29 am
Thanks Mike
I'll study your routines and try to "pic" the bones out.
Cheers
Stew
Title: Re: Help writing pic code
Post by: megatron on October 29, 2014, 05:04:50 pm
Hi all
well I'm close but still no cigar.
I'm having a problem adding a calibration routine. I want the program to go to a calibration subroutine if the unit is powered on while a push button is pressed.
For some reason it is not recognizing that porta,2 is set even though I have weak pullups enabled.
If I add an external resistor all is well but I would like to use the internal pull up resistor.
I have a push button connect between ground and porta,2.
If I test the pin with a meter the weak pullups appear to be working, is there perhaps a delay before the pullups are enabled?

Here is the code that I am using, there is probably a glaring mistake but I'll be damned if I can find it.
Help please
Stew

; EQUATES SECTION

TMR0              EQU        H'01'    ;means TMR0 is file 1.   
STATUS           EQU        H'03'    ;means STATUS is file 3.   
PORTA            EQU        H'05'    ;means PORTA  is file 5.   
PORTC           EQU        H'07'    ;means PORTB is file 7.
INTCON          EQU        H'0B'    ;INTCON is file 0BH
TRISA             EQU        H'85'    ;TRISA (the PORTA I/O selection) is file 85H
TRISC             EQU        H'87'    ;TRISC (the PORTC I/O selection) is file 87H
OPTION_REG     EQU        H'81'    ;the OPTION register is file 81H   
ZEROBIT         EQU        H'02'    ;means ZEROBIT is bit 2.   
WPUA             EQU        H'95'    ;weak pull-ups is file 95H
ANSEL            EQU        H'91'    ;analogue select register
CMCON0        EQU        H'19'    ;comparator configuration register
ADCON0         EQU        H'1F'    ;adcon0 register
ADCON1         EQU        H'9F'    ;adcon1 register
ADRESH          EQU        H'1E'    ;adresh register
ADRESL          EQU        H'9E'    ;adresl register
COUNTERA     EQU        H'20'    ;countera register
COUNTERB     EQU        H'21'    ;counterb register
COUNTERC     EQU        H'22'    ;counterc register


;*********************************************************

    LIST    P=16F684    ; we are using the 16F684.
    ORG        0            ; the start address in memory is 0
    GOTO    START        ; goto start!

;**********************************************************************
; Configuration Bits
    __CONFIG    H'3084'

;*********************************************************

START   
    BANKSEL    TRISA   
    MOVLW   B'00101101'    ;porta bits 0, 2, 3 & 5 are i/p
    MOVWF   TRISA
    MOVLW    B'00001010'    ;portc bits 1 & 3 are i/p
    MOVWF    TRISC       
    BSF          OPTION_REG,7
    MOVLW    B'00110111'    ;weak pull-ups enabled
    MOVWF    WPUA        ;on PORTA pins 0,1,2,4,5
    CLRF        ANSEL        ;ports set to digital i/o
    BANKSEL    PORTA
    MOVLW    H'07'
    MOVWF    CMCON0        ;comparators off digital i/o
    CLRF        PORTA        ;CLEARS PORTA
    CLRF        PORTC        ;clears PORTC.
    BTFSS      PORTA,2        ;test for calibrate switch press
    CALL       CALIBRATE
Title: Re: Help writing pic code
Post by: TurboTyne on October 29, 2014, 06:35:47 pm
Hi Stew

I was wondering how you've been getting on.

I've never used the pull-ups so was interested by your query since it prompted me to learn a little about this feature of the PICS.
So please bear in mind that I have not dabbled with these settings myself, however, I noticed the following in the data sheet regarding the OPTION register:

bit 7 RAPU: PORTA Pull-up Enable bit
1 = PORTA pull-ups are disabled
0 = PORTA pull-ups are enabled by individual PORT latch values

I see that your code sets OPTION bit 7 and it seems that this should disable the pull-ups. Do you set this bit for a reason that I'm not aware of or could this be the cause of the problem?

But, you say the pin appears to be high when tested with a meter. I just wonder how meaningful was your test. e.g. did you connect the pin to ground via a high value resistor while making the measurement? If not, I wonder if the voltage on the pin would have drifted high even if pull-ups were disabled, since the inputs will be high impedance and presumably so was your test meter.
Hopefully Ian will have some more expert comments on this.

Regards,  Mike
Title: Re: Help writing pic code
Post by: megatron on October 29, 2014, 07:04:26 pm
Thanks Mike
Option_reg bit 7 should indeed have been 0. Probably the only place where 0 means on and 1 means off.
I must learn to read the datasheet more thoroughly.
Thanks again
Stew
Title: Re: Help writing pic code
Post by: megatron on November 03, 2014, 02:42:26 pm
Well I finally got to smoke that cigar.

I would like to thank everyone who helped me with this project, I certainly couldn't have done it without you.

There is 1 slight niggle though. When the power is switched on the servos give a little twitch to the right, not much but enough to extinguish the pilot light.
I don't think this is a problem with the code as it also happens with the pic removed from the circuit. I have googled this problem and there are lots of questions about it but no answers as far as I can see.
Has anyone experienced this and come up with a solution? It appears to happen if power is supplied to the servo before it receives a signal.

How about that pint Mike?

Regards
Stew
Title: Re: Help writing pic code
Post by: Mad Scientist on November 03, 2014, 10:06:06 pm
Congratulations on completing the project!  :-)) It's been fascinating to watch it all come together.

Tom
Title: Re: Help writing pic code
Post by: TurboTyne on November 04, 2014, 10:43:03 am
Hi Stew

Well done! 

Is your control system in a model boat at present?
Do you have plans for further PIC projects now you've learnt a lot about using the devices?

RE: that pint, it would certainly be good to meet up and I'd be very interested to see your boiler etc.

Maybe we can get in touch again via PM?

Regards

Mike
Title: Re: Help writing pic code
Post by: flashtwo on November 04, 2014, 04:05:38 pm
Congratulations Stew on climbing that steep learning curve - well done mate!

Re the pilot gas valve servo, I suppose you relight the pilot after the servo has settled down. To be clever, you could get the PIC to operate a relay that applies power to the servo after a PWM signal is present.

I had a similar problem with the ESCs powering the water pump motors. On switch on the ESCs wanted to see a 1ms PWM for a few seconds before the pump speed PWM (>1ms) was applied otherwise the ESCs wouldn't start. The PIC was programmed to apply the 1ms signal as required.

Also, I wanted the main gas control valve to be properly shut at start up so the PIC was programmed to open slightly and then apply a shut value. Doing it this way over came any stiction. Your code can now be modified with ease to over come these slight niggles.

Your project was a useful revision course for us all!

Ian
Title: Re: Help writing pic code
Post by: megatron on November 04, 2014, 07:24:57 pm
Hi Mike
The system is not actually in a boat at the moment.
I was given a boat with a Cheddar Proteus plant fitted with a Cheddar ABC system. I thought it would be a nice project to try and build a similar system, and so the story began.
I started building the first box with very little electronics knowledge, learning curve no.1. I then wanted to take it to the next level and build using a pic or similar and that's when this episode started. It's amazing how much knowledge I've gained simply because someone gave me a model boat.

I would again like to thank everyone who has helped and encouraged me through this project, I couldn't have done it without you.

I think my next project is going to be a Sun following solar panel and charging system for when I'm away camping.

I'll pm you Mike when I've got this mounted in an enclosure and let you see what I've built.

Thanks
Stew
Title: Re: Help writing pic code
Post by: megatron on December 03, 2014, 05:30:20 pm
Hi Everybody I'm back.
I'm trying to make something that will allow me to operate 2 systems from a single radio channel.
To do this I need to measure the length of the pulse from the radio receiver.

The PIC will be running at 4mhz and tmr0 will have a prescaler of 4.

The pulse will be between 1-2ms.

My plan is to wait until the pulse starts, start tmr0, wait until tmr0 = 250 (1ms), clear tmr0, wait until pulse finishes and read tmr0.

The code I have written so far for the 1ms delay is this

BEGIN
    BANKSEL    PORTA
    BTFSS    PORTA,3
    GOTO    BEGIN
    CLRF    TMR0
DELAY1MS
    MOVLW    D'250'
    SUBWF    TMR0,0
    BTFSS    STATUS,0
    GOTO    DELAY1MS
    CLRF    TMR0

The problem is the number of instruction cycles used. Is there a way to do this using fewer cycles?

Cheers
Stew
Title: Re: Help writing pic code
Post by: flashtwo on December 03, 2014, 06:22:03 pm
Hi Stew,
This is a good example where the interrupts are useful.

Within the Interrupt Routine at the very start of the code, the external interrupt (i.e. the radio PWM signal) is detected and it is determined whether it is the rising or falling edge.

If it is the rising edge then start a timer, then depart from the interrupt routine and carry on with the other tasks.

If the external interrupt is caused by a falling edge, then stop the timer and read the value of the timer into your variable.

   BTFSS   INTCON, INTF   ; Test for external interrupt.
   GOTO   EXIT      ; Go to Interrupt Routine Exit
   BCF    INTCON, INTF   ; Clear the External interrupt interrupt flag.

   BTFSS   OPTION_REG, INTEDG   ; Is it a rising edge external interrupt,
               ; if so skip the next instruction.
   GOTO   FALLING_EDGE      ; It must be a falling edge interrupt.
   GOTO    RISING_EDGE      ; It must be a rising edge.

The timer value may have to be scaled according to its use in the other code. I found it best to scale it within the interrupt routine and export as a different variable; this avoids the required value being mysteriously changed in the non-interrupt part of the code i.e. the interrupt could change the value just as you are doing the scaling (bitter experience!).

Using the interrupt saves cycling around the same bit of code and holding up other tasks.

One additional feature is to detect loss of radio signal. In the same interrupt above you could set another timer (another interrupt!) which times out at 25ms if the rising signal doesn’t reset it after the standard 20ms gap. The loss of signal could be used to shut the gas valve.

Ian.
excuse the "tabbing", it never works properly.
Title: Re: Help writing pic code
Post by: megatron on December 03, 2014, 06:51:50 pm
Hi Ian
As the pulse is between 1-2ms I was wanting to wait 1ms before timing the pulse in order to keep the resolution as high as possible.
This 1ms would then be factored in at the end.
Is it possible to use interrupts to start and stop the timing after the first 1ms?
Stew
Title: Re: Help writing pic code
Post by: flashtwo on December 03, 2014, 10:51:47 pm
Hi Stew,

I've been using Timer 1 which has a 16 bit resolution and counts in 1us increments, giving 0.1% resolution.

In my application I wanted a value of 0 to 1000 to represent Feed Flow demand of 0 to 200cc/min, therefor I subtracted 1000 from the Timer 1 value of 1000 to 2000us. I also use the Feed flow demand signal to enable the Gas Valve to open; above a certain value  (about three clicks on the transmitter joy-stick) the valve is allowed to start to open - below that value the Gas Valve has a hard shut signal.

The value of 0 to 1000 originally was the desired engine speed, but when that scheme failed to work, I used the value for feed flow - I suppose I could have used Timer 0, but that got used for loss of radio signal timeout.

You can certainly enable and disable the particular interrupts, e.g.  using INTE for the external interrupt, then using Timer 0 you would have 0.4% resolution which would be more than enough.

Ian
Title: Re: Help writing pic code
Post by: megatron on December 04, 2014, 09:20:34 am
Hi Ian
Perhaps I should explain what I'm trying to do.

I want to control the throttle and the forward/reverse servos from the same stick.

When the stick is in the central position the throttle will be closed and the f/r servo is in the forward position. As the stick is pushed forward the throttle is progressively opened. When the stick is pulled back from centre the f/r servo moves to reverse and the throttle is again opened.

As you can see, half the travel on the stick equates to full travel on the throttle servo, halving the resolution.
If I used tmr0 to measure the full 2ms I would have to use a prescaler of 8, again halving the resolution.

Using tmr1 would be ideal but I'm not confident enough to do the maths on a 16 bit number.

I think I'll use the 1ms routine that I used in the previous project to measure the first 1ms and then either use a modified version of it or tmr0 to measure the remainder.

I don't think there is any point in using interrupts, other than as a learning exercise, as the program has nothing else to do until the pulse length has been acquired.

Perhaps if you have the time you could do a couple of short tutorials on interrupts and using 16bit numbers. I'm sure there are a few people on here who would benefit.

Cheers
Stew
Title: Re: Help writing pic code
Post by: TurboTyne on December 04, 2014, 11:45:42 am
 Hi Stew
 I’ll have a stab at 16-bit numbers which are really nothing to be scared of, especially if you are just working out a value to place in a timer register. Sorry if this is all too basic.

There are several ways of thinking about a 16-bit number, but maybe the simplest is to think of it as a two-byte number and forget about the 16 individual bits, at least for the time being. These 2 bytes are designated the upper and lower byte or the Most Significant Byte (MSB) and Least Significant Byte (LSB). In the details of16-bit timer registers you can see these designations.

So from the bottom up, as you know, a one-byte number can store decimal values from zero up to 255. If you have the value 255 in the lower byte and you increment it, the value of the byte returns to zero and the carry bit in the status register becomes set.  This is analogous to, in the decimal system, counting from zero up to 9 and then incrementing by one. In that case the units integer returns to zero and a one is carried over to the tens integer to make “10”.  With two-byte numbers, the carry is used to increment the upper byte of the 2-byte value. So every unit in the upper byte represents 256 in the overall two-byte value.

Therefore, to work out the value of a two-byte number you multiply the value stored in the upper byte by 256 and add the result to the value in the lower byte. Conversely, to work out the values to be placed in the 2 registers that store the two-byte number, simply divide the value of the number by 256. The whole number after rounding down is the value to place in the upper byte. Then work out the remainder and store that in the lower byte. E.g. to store 2000:  2000 divided by 256 = 7.8125  So place the decimal value 7 in the upper. Then 2000 – (7 X 256) =208. So place the decimal value 208 in the lower byte. You can check the answer by working backwards. i.e. upper byte X 256 + lower byte 208 should give 2000.

Things get a bit more complicated when you start doing maths with 16-bit values. Addition is easy. You add the two lower bytes and if carry is set you increment one of the upper bytes to be added together. Then you add the 2 upper bytes together. You need to be sure that the result is less than 65,535 since in that case you would need to employ 24-bit values.  If and when you need it, can post  subroutines that carry out 16-bit and/or 24/ 32-bit multiplication and division and also code for adding or subtracting multiple byte values.


Regards  Mike

 
Title: Re: Help writing pic code
Post by: megatron on December 04, 2014, 12:28:13 pm
Hi Mike
I understand the principle of 16bit numbers being in 2 bytes and I could probably handle addition ok, but I also have subtraction, multiplication and division to do.
I would be very interested to see the routines you use.
Have you tried using any of the 16bit or 32bit pics?
regards
Stew
Title: Re: Help writing pic code
Post by: TurboTyne on December 04, 2014, 01:42:26 pm
Hi Stew

No, I've never used any PICs other than the 16F's. Many years ago I started teacvhing myself C, and I liked that language compared to the Turbobasic I'd used previously. But, now I like the assembler coding as I feel close to the action and, so far, these PICs can do more than I need.

Below is the code I use for multiplying. As it says, it handles two 16-bit values (signed or unsigned) and gives a 32-bit result.
I'll sort out the division and subtraction code in a while.

I initially obtained these routines at http://www.piclist.com/techref/microchip/math (http://www.piclist.com/techref/microchip/math) and they ask to link to their site rather than copy. Trouble is, my routines have been modified from the original and I know my code works fine.

One other point to bear in mind. I use PICs that have the extended mid-trange instruction set. I cannot remeber if any of the extended instructions are used in these routines.

Regards
Mike

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Combined sub-routines to multiply 2 16-bit numbers to a 32-bit product.
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

;  registers used: 
;                    product(4 bytes)
;                    m_plier(2 bytes)
;                    m_plicand(2 bytes)
;                    bitcount
; flag register:
;             misc_flags bit:    MULT_NEG    ; setting this bit signifies m_plier was negative


;*********************************************************************************************
;            Call subroutine starting here when m_plier is signed.
;*********************************************************************************************
multiply_signed_16to32

;    Test sign of m_plier and reverse if negative.

            BANKSEL        m_plier
            btfss        m_plier+1, 7        ; is sign bit set?       
            goto        multiply_16to32

            comf        m_plier, F            ; sign of m_plier is -ve so make 2's compl
            comf        m_plier+1, F
            incfsz        m_plier, F                ; If result of incr is not zero, then no need to adjust high byte
            goto        _set_flag
            incf        m_plier+1, F
_set_flag
            BANKSEL        misc_flags
            bsf            misc_flags, MULT_NEG            ; m_plier negative so set flag
            goto        _clear_product

;*************************************************************************************************
;            Call subroutine starting here when m_plier is unsigned.
;*************************************************************************************************
multiply_16to32

            BANKSEL        misc_flags
            bcf            misc_flags, MULT_NEG            ; ensure flag shows result is +ve

_clear_product
            BANKSEL        product
            CLRF        product
            CLRF        product+1
            CLRF        product+2
            CLRF        product+3
            BANKSEL        bitcount
            MOVLW        d'16'            ; 16 bit operations
            MOVWF        bitcount

_mult32_1
            BANKSEL        m_plier
            RRF            m_plier+1, F    ; shift both bytes of multiplier down
            RRF            m_plier, F
            BTFSS        STATUS, C        ; If carry is set, then least sig bit was 1 so add current value of multiplicand to product
            GOTO        _mult32_2            ; carry not set so skip addition

            BANKSEL        product+4
            CLRF        product+4
            BANKSEL        m_plicand        ; start 16-bit addition
            MOVF        m_plicand+1, W
            BANKSEL        product
            ADDWF        product+3, F
            BTFSC        STATUS, C        ; check if a carry to byte-4 is needed
            INCF        product+4, F

            BANKSEL        m_plicand
            MOVF        m_plicand, W
            BANKSEL        product
            ADDWF        product+2, F
            BTFSC        STATUS, C        ; check if a carry to byte-1 is needed
            INCFSZ        product+3, F
            GOTO        $+2
            INCF        product+4, F           
_mult32_2
            BCF            STATUS, C        ; ensure carry bit is clear, then rotate m_plicand bytes upwards
            BANKSEL        product        ; rotate low byte first so any carry is accomplished automatically.
            RRF            product+4, F
            RRF            product+3, F
            RRF            product+2, F
            RRF            product+1, F
            RRF            product, F

            BANKSEL        bitcount
            DECFSZ        bitcount, F
            GOTO        _mult32_1
           
;            Lastly test to see if result must be converted to 2's complement

            BANKSEL        misc_flags
            btfss        misc_flags, MULT_NEG
            return
            BANKSEL        product
            comf        product, F
            comf        product+1, F
            comf        product+2, F
            comf        product+3, F

            incfsz        product, F
            return
            incfsz        product+1, F
            return
            incfsz        product+2, F
            return
            incf        product+3, F
            return
Title: Re: Help writing pic code
Post by: TurboTyne on December 04, 2014, 02:59:48 pm
Hi again

Here is the divide subroutine. If you only need to divide a 16-bit number then you just set the unwanted upper byte to zero. No doubt you'd get code that is a bit shorter and faster if it is specific for 16 bit by 16bit division, but I just use this one routine to keep life simple(r).

By the way, there are various ways in use top name the bytes in multi-byte variables. Some people define a different name for each register. I generally define one name for all the registers in a CBLOCK directive such as:

    CBLOCK    0x20
                dividend:3
                divisor:2
                dividend:2
                bitcount
# insert here other variables

    ENDC

This gives makes the name "dividend" refer to the first byte and the value 3 after the colon makes the assembler reserve a total of 3 bytes before assigning the next address to a new name.

Then, one has to be consistent about whether the first byte is the least or the most significant. In these routines I always use the first byte as the LSB. Then, if, for example, I wanted to move the lowest and then the highest bytes of the dividend to W register, I'd write:

movf  dividend, W
..........

movf  dividend+2, W

The assembler adds 2 to the value of the address assigned to "dividend" and places the result of that addition in the machine code that defines the address to be read.

Its crucial to get the byte order correct.

Mike


;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Sub-routine to divide a 24-bit number by a 16-bit number to give a 24-bit quotient.
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; This routine was written by Nikolai Golovchenko (http://www.piclist.com/techref/microchip/math/div/24by16.htm (http://www.piclist.com/techref/microchip/math/div/24by16.htm))
;    Names of registers have been changed to make it easier to follow etc.
;    Registers: dividend (3 bytes), divisor (2 bytes)
;    Registers: remainder (2 bytes), bitcount (1 byte)

divide_24_16

            BANKSEL        remainder
            CLRF        remainder
            CLRF        remainder+1
            MOVLW        d'24'
            MOVWF        bitcount
_div_1
            RLF            dividend, F
            RLF            dividend+1, F
            RLF            dividend+2, F
            BANKSEL        remainder
            RLF            remainder, F            ;    shift carry into remainder
            RLF            remainder+1, F
            BANKSEL        bitcount
            RLF            bitcount, F                ; save carry in bitcount

            MOVF        divisor, W                ;  subtract divisor from remainder
            BANKSEL        remainder
            SUBWF        remainder, F   
            BANKSEL        divisor
            MOVF        divisor+1, W
            BTFSS        STATUS, C
            INCFSZ        divisor+1, W
            SUBWF        remainder+1, W            ; keep that byte in W until we are sure about the borrow.

            BTFSC        STATUS, C                ; if no borrow
            BSF            bitcount, 0                ; set bit zero of bit counter (saved carry)

            BTFSC        bitcount, 0                ; if no borrow
            GOTO        _div_2

            MOVF        divisor, W                ; restore remainder if borrow
            ADDWF        remainder, F
            MOVF        remainder+1, W            ; read high byte of remainder to W,
                                                ; to not change it by next instruction
_div_2
            MOVWF        remainder+1                ; store high byte of remainder
            BCF            STATUS, C                ; clear carry
            RRF            bitcount, F                ; and restore counter

            DECFSZ        bitcount, F                ; decrement bit counter
            GOTO        _div_1                    ; repeat loop if not zero

            RLF            dividend, F                ;  shift in last bit of result
            RLF            dividend+1, F
            RLF            dividend+2, F           
            RETURN


Title: Re: Help writing pic code
Post by: TurboTyne on December 04, 2014, 03:35:49 pm

Hi Stew

Last offering of code. I know all four of these maths procedures work but I wouldn't be at all surprised if Ian comes up with some better versions.

I don't use subroutines for subtraction or addition. Here are the blocks of code that do the jobs.

I have put in some dummy names into this section. This code adds 16-bit varA to 16-bit varB, result in varB
 
          BANKSEL        varA
            movf            varA, W
            addwf            varB, F
            btfsc            STATUS, C                ;     If carry set then increment upper byte
            incf            varB+1, F
            movf            varA+1, W
            addwf            varB+1, F

The following code subtracts 16-bit constant defined as MAX_FSPEED_MSB / MAX_SPEED_LSB  from 16-bit variable "Fpump_speed" with the result placed in 16-bit variable "temp". The result of this is a signed value. i.e. if the result is negative, then bit 7 of temp+1 =1, otherise it is 0.

            movlw            MAX_FSPEED_MSB        ;    Place msb in temp+1
            movwf            temp+1
            movlw            MAX_FSPEED_LSB            ;    Place lsb in temp
            movwf            temp
            movf            Fpump_speed, W            ;      subtract lsb from max value
            subwf            temp, F
            movf            Fpump_speed+1, W        ;      subtract msb from max value
            btfss            STATUS, C
            incfsz            Fpump_speed+1, W
            subwf            temp+1, F
Title: Re: Help writing pic code
Post by: megatron on December 04, 2014, 05:14:03 pm
Hi Mike
Thanks for those routines. I'll look through them and try to figure out what's going on.
In the mean time I'll stick to using 8bit numbers.
I've looked on the piclist website you mentioned and they have a lot of useful routines but they're not half complicated.
Cheers
Stew