PDA

View Full Version : 12F683 - basic code not working



Scampy
- 14th January 2014, 20:30
Hi Guys,

Playing about with a 12F863 chip for a small project, but to start with thought I would do the basic LEDs flash to ensure programming and that the PIC runs. The code compiled, and ran, flashing the LED on RA0 (on the EasyPIC5 board, which corresponds to GPIO.0). I then added a simple "if then" statement so that if a switch was pressed taking GPIO.1 low the code would jump to the section to flash the LED. But when compiled and loaded to the chip the LED still continues to flash regardless if the switch is pressed or not. I've enabled the pull up on the development board which has no effect



ASM
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF
endasm

TRISIO = %11111110
ANSEL = 0
GPIO.0 = 0
CMCON0=7

Motor var GPIO.0
Switch1 var GPIO.1
Switch2 var GPIO.2

main:
If Switch1 = 0 then
goto demo
else
goto main

demo:
high Motor
pause 1000
low Motor
pause 1000
goto main
endif
Goto main


Any ideas why ?

Scampy
- 14th January 2014, 20:48
Interestingly this works



ASM
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF
endasm

TRISIO = %11111110
ANSEL = 0
GPIO.0 = 0
CMCON0=7

Motor var GPIO.0
Switch1 var GPIO.1
Switch2 var GPIO.2

main:
If Switch1 = 1 then
gosub demo
endif
goto main

demo:
high Motor
pause 1000
low Motor
pause 1000
goto main
REturn

Acetronics2
- 14th January 2014, 20:54
Hi, Malc

I would have written ...



ASM
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF
endasm

TRISIO = %00111110
ANSEL = 0
GPIO.0 = 0
CMCON0=7

Motor var GPIO.0
Switch1 var GPIO.1
Switch2 var GPIO.2

main:

If !Switch1 then

demo:
high Motor
pause 1000
low Motor
pause 1000
endif

goto main



but it's just me ...

at least, your "endif" should be placed just before the " demo " label ...

cause the " IF " condition never sees the " ENDIF " condition reset ....

tadaaaaaa ... :rolleyes:

Alain

AvionicsMaster1
- 15th January 2014, 16:22
I'm assuming your using PBP3 and to do configs you need to do them like this and both "config" lines need to be in caps. I know PBP2.6 was different but with either version both "config" lines need to be in caps.

#CONFIG
;configuration directives in Assembly Language
#ENDCONFIG

TRISIO on the 12F683 is only 6 bits wide so I'm wondering if you need to change it to TRISIO = %111110. I think when you set the TRISIO and the GPIO as input and low respectively you'll always have a low at GPIO.0. When you set the pin low and told it to wait for a low it did what you told it to do. That is go to the demo subroutine. Since you changed it to =1 you had a state change and the chip could sense that. The reply by Acetronics2 did that by using the ! sign.

Your second take on the subroutine and endif look better.

As usual I'll await for someone to tell I'm wrong.

Scampy
- 15th January 2014, 19:21
I'm assuming your using PBP3 .

Sorry, wrong assumption :) - using 2.60

Quick question and slightly off topic, but related to this project... I'm using an H-bridge to control the motor as I need it to be bi-directional. I've been experimenting with some NPN and PNP transistors that I had in my hobby box, BC639 and BC640 and have had a small low current motor running from the PIC. However the actual motor I will be using is a 540 type with a 6:1 gearing. Even though it will be running from a 3v supply (separate to the 5v pic supply) my guess is that the current might be too high for the BC639 / 640 transistors. Can anyone advise if using these transistors would be OK for such a motor, or should I use something like the TIP220 transistors ??

wdmagic
- 19th January 2014, 00:23
I would use FET's, or a L298 chip. the 298 works great. the FET's i use are a bit overkill for what your doing but you can get lower values.
some that work well for all hobby motors from the old style that were in tape decks to modern RC racecars is
RFP12N10L
IRF540
IRF9530

Scampy
- 19th January 2014, 14:15
Following suggestions I've ordered a module from e-bay based on an L298N controller, which should work as under testing the 540 motor was drawing 0.7A and these things are rated at 2A.

I'm now working on the light detection side of the circuit. Basically the idea is to automatically open a door at dawn (wife now keeps chickens !). So when the light level reaches or exceeds a threshold, the motor runs, opening the door until the door hits a micro switch which then changes a pin status which then turns off the motor.

I've purchased a 16k-33K LDR from Maplin ( http://www.maplin.co.uk/p/16k-33k-ohm-light-dependent-resistor-n57ay ) and connected that from the 5v line to GPIO.0 and covering the LDR makes the associated LED on my development board go out, and increase in brightness due to ambient light or when a bright torch is shon on the LDR. So the resistance is varying based on the light level, so far so good. Now the issue I'm having is that having set the ACD to 8 bits this should give me a 0 - 254 range of values... but in testing to get the motor to run at various values, these are not what I would expect.

Here's the test code:



ASM
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF
endasm

' Hardware configuration
' ======================



TRISIO = %001111
ADCON0 = %10000001
ANSEL = %00110011
DEFINE ADC_BITS 8
DEFINE ADC_SAMPLEUS 50
CMCON0=7

Motor1 var GPIO.4
Motor2 var GPIO.5
ADChannel0 var word

GPIO = 0 ' clear all output
Pause 50 ' internal oscillator settle time

main:
low Motor1
low Motor2
adcin 0,adchannel0 ' Read AN0

If adchannel0 >2 then
high Motor1
Low Motor2
pause 5000
low Motor1
low Motor2
endif

goto main


If I put in <1 for the argument, the motor runs even with the LDR covered. If I put in >1 the motor won't run unless I shine the torch directly on the LDR. I'm sitting here in ambient light with the sun shining in the window so the motor should be running.

Any ideas as to what I'm doing wrong ?

Demon
- 19th January 2014, 14:39
Do you use a word for 8 bit as well?

Motor2 is never going on by the way.

Robert

Scampy
- 19th January 2014, 14:52
OK corrected that (original example code must of been for higher resolution...) but still no joy in setting the thresholds

Motor two is always off in this example as its the other terminal to the H bridge

aratti
- 19th January 2014, 16:18
You should post the schematic of your project in order to get proper help. Very likely your problem is in the hardware arrangement.

Cheers

Al.

Scampy
- 19th January 2014, 17:33
Al,

The PIC is on an EasyPIC5 development board, but basically this is the schematic. I've also tried replacing the LDR with a 10k pot and whilst the LED on the dev board dims in brightness the threshold values still have the same effect. Placing the LDR between +5 and GPIO.0 gives a better range of brightness in the LED (not shown in the schematic) from off when the LDR is covered, to bright when an LED torch is placed directly over the LDR.

I don't program much, so often feel like a newbie when I dust off the development board, and ADC is something I've only once played with. As far as I can understand, the voltage on GPIO.0 should be converted into a byte value between 0 and 254, so I could set the threshold at which point GPIO.4 is made high ?

Demon
- 19th January 2014, 17:41
Shouldn't there be protective diodes "somewhere" whenever a motor is used?

I don't really get how that motor is wired. I would expect a pulse method, but the code is constant on for 5 seconds.

Admittedly confused.

Robert

Scampy
- 19th January 2014, 18:03
Robert,

I grabbed the h-bridge circuit from a web site, which using pnp / npn transistors works ok for the test motor (see above). I will be using an H-bridge chip for the larger motor.

Yes for testing I have the motor running for 5 sec once the threshold has been breached

AvionicsMaster1
- 19th January 2014, 18:44
I think you need a voltage divider network for the LDR. As it is the voltage on your ADC input line will always be 5VDC.

I also wonder about the capacity of your transistors. The stall current on the some of the motors I found was 46 Amps. If the motor were to stall, your transistors would burn out with unknown consequences. If you want to use this motor I'd put a fuse in the supply line to limit current during stalls.

Typically motors make alotta noise when running. I think it's a great idea to separate the power supplies. Just make sure to make the low side connected between the two systems.

My intimation of TRISIO is relevant to PBP2.6 also. I'm not sure if PBP starts with LSB when reading the TRISIO and quits after 6 bits or starts at the MSB and quits after 6 bits. I do know the 12F683 only has 5 I/O pins and one I only pin so your TRISIO statement should be 6 bits wide.

Scampy
- 19th January 2014, 18:55
Thanks for the comments:

I've tried using the LDR in series with a 10K pot between 5v and GND, connecting GPOI.0 to the junction between them and still can't get anything meaningful for the value of the variable that stores the ADC readings.

I've corrected the code thus:



ASM
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF
endasm

' Hardware configuration
' ======================



TRISIO = %001111
ADCON0 = %10000001
ANSEL = %00110011
DEFINE ADC_BITS 8
DEFINE ADC_SAMPLEUS 50
CMCON0=7

Motor1 var GPIO.4
Motor2 var GPIO.5

ADChannel0 var byte

GPIO = 0 ' clear all output
Pause 50 ' internal oscillator settle time

main:
low Motor1
low Motor2
adcin 0,adchannel0 ' Read AN0

If adchannel0 >10 then
high Motor1
Low Motor2
pause 5000
low Motor1
low Motor2

endif


goto main

aratti
- 19th January 2014, 20:39
Check the risistence of your LDR in both condition (dark and light). Since the lowest resistance should be found in light, use this value for your devider network. In this way you should have a value in volts near to zero in dark and near to Vdd/2 in light, more than enough to be sure to trip the system at the right time.

By the way the schematics of your Hbridge is wrong! NPN should be connected on the low side, while PNP should be connected on the high side.

Follow the wise suggestion given above, always use freewheel diodes when using inductors!

Cheers

Al.

Scampy
- 19th January 2014, 22:02
Al,

My fault, I drew the schematic the wrong way round (I was rushing :) ). I've now placed diodes between the collector and emitters of each transistor as suggested.

Measuring the LDR I get a few hundred ohms when the torch is directly into the face of the LDR and around 2.1m ohms when I place my finger over it. Under the ambient light in the room it was averaging 16K - 18K. I've tried placing the LDR and an 18k resistor in series between +ve and GND and then connecting GPOI.0 to the junction between the two. The LED on the development board was lit quite bright and covering the LDR had no effect. I then used a 200 ohm resistor based on the fact that in light the resistance was a few hundred ohms when tested.

With the 200 ohm resistor in place as a voltage divider with the LDR, under normal room light with a value of adchannel0 >2 in the if then statement the motor runs. If I change that to adchannel0 >3 and re-compile the motor won't run regardless of bright light or darkness.

With the divider made up as the LDR between +5v and GPOI.0, and the 18K between GPIO.0 and GND I get 0.6v on GPIO.0 when the ldr is covered, and around 3.5v with the torch shone directly at the ldr. So I would assume this voltage range of 3v should be enough for the ADC to read ? so why is it that the ADC is acting more like a switch with a value of 1 rather than 255 steps ?

aratti
- 20th January 2014, 07:38
Add the following defines on top of your code:

DEFINE ADC_BITS 8
DEFINE ADC_CLOCK 2
DEFINE ADC_SAMPLEUS 50

Cheers

Al.

Scampy
- 20th January 2014, 09:02
Hi Al,

I've modded the code so I can see what's going on.




ASM
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF
endasm

TRISIO = %001111
ADCON0 = %10000001
ANSEL = %00110011
DEFINE ADC_BITS 8
DEFINE ADC_SAMPLEUS 50
DEFINE ADC_CLOCK 2
CMCON0=7


Tx var GPIO.5
ADChannel0 var byte

GPIO = 0 ' clear all output
Pause 50 ' internal oscillator settle time

main:
adcin 0,adchannel0 ' Read AN0
Serout2 Tx,84, ["val: ",#adchannel0,10]
pause 5000

goto main


The divider made up as the LDR between +5v and GPOI.0, and the 18K between GPIO.0 and GND.

Compiled the code and loaded it to the chip. Opening the serial tool in Micro-studio I get a value of 1 when the LRD is in ambient light or covered and 2 with the torch shone directly on it.

Ideas ??

Scampy
- 20th January 2014, 09:44
As a postscript, i wired a 10K pot between +5v and GND with the wiper to GPIO.0 and got the same results - seems the ADC isn't working

Scampy
- 20th January 2014, 10:03
OK I'm going to throw this thing out the window in a moment

I downloaded a sample code from this forum written by Bruce




ASM
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF
endasm

DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 3
DEFINE ADC_SAMPLEUS 50
number VAR word

'CMCON = 7 ' Comparators off
ANSEL = %00000001 ' GPIO.0 A/D in, rest digital
ADCON0.7 = 1 ' Right justify for 10-bit
GPIO = %00000000 ' Initialize outputs
TRISIO = %00000001 ' GPIO.0 = input, rest outputs
Tx var GPIO.5


main:
adcin 0,number ' Read AN0
Serout2 Tx,84, ["val: ",#number,10]
pause 5000
goto main




With the 10K pot wired between the supply with the wiper to GPIO.0 and get readings between 437 and 440 !!!!!!!!!!!!!! - still just three digits between min and max.
I had to rem out the CMCON line - presumably the 12F683 has no comparators, would that be the case.

Archangel
- 20th January 2014, 11:11
Hi Malcolm,
Comparator register for this chip is CMCON0 set CMCON0=7 to turn off as per data sheet 8.3
It compiles. You might have to set the CCP1CON to zero too , not sure about that though.

HenrikOlsson
- 20th January 2014, 11:16
Hi,
I haven't been following this thread but why do you say presumably the 12F683 has no comparators, would that be the case ?

Why not simply open the datasheet and have a look? Sure enough, the 12F683 DOES have a comparator and it's control register is CMCON0 - which you had got correct in your previous snippets of code but not in the latest one. I'm not saying this is the problem though.

Verify that ALL your grounds/commons are connected, as you move the wiper of the pot measure the voltage right at the PIC, between pins 8 (Vss) and 7 (AN0) to verify that it's not a loose connection or floating ground etc.

/Henrik.

Scampy
- 20th January 2014, 12:01
OK, I've removed the breadboard connection from the EasyPic5 and configured the board to use the 10K pot on the EasyPic5. I have the USB/Serial breakout board connected to +5v, GND and GPIO.5 and confirmed the communications were OK in the serial monitor window. I've added the correct setting for the comparators (must of removed the 0 at the end of the statement when editing the file- my bad :) ).

Loading the code I can get 0 - 1023 by moving the wiper on the EasyPic5 board, so the chip is reading 0-5v and converting that to a digital value.

I then added back the lines for the motor control, making them GPIO.2 and 4, and hooked up the H-Bridge on the breadboard - I added the trigger of 100 in the line "if number >100 then turn on the motor" and watched what happened when I turned the pot on the easyPic5 board and low and behold, when the value hit 101 the motor came on......

I'm going to pull all the connections off the breadboard and re-check the wiring - seems that the issue is external and not the code. One possible cause could be the resistance / capacitance nature of the breadboard causing the issue ??

Anyway, thanks guys for your comments and input.... as always it's nice to receive assistance and helps with the learning curve

Malcolm

Scampy
- 21st January 2014, 15:26
Hi again,

I'm stumped on what's happening when I run the following code, and having gone over it time and time again I might be overlooking the obvious.

I have a motor connected to the H-bridge module that arrived yesterday - making pins 1 high and 2 low makes the motor run one way and reversing which pin is high and low makes the motor run the opposite way. I'm using a separate 9v supply for the motor.

When first turned on, the threshold set means that the code is set to night mode. I then shine a light on the LDR and the motor runs until I connect GPIO.5 to 5v to simulate the door closing the micro-switch at the end of its travel. So far so good. However, if I remove the connection between GPIO.5 and +5v to simulate the door in the close state GPIO.5 remains latched high. Grounding the pin momentarily has no affect, and disconnecting the H-bridge has no affect. Only way to clear this is to turn off and on the EasyPic5 board.




ASM
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF
endasm

DEFINE ADC_BITS 10 ' ADC resolution
DEFINE ADC_CLOCK 3
DEFINE ADC_SAMPLEUS 50
number VAR word ' Variable to store ADC result
day var byte ' Variable to indicate day or night

CMCON0=7
CCP1CON=0
ANSEL = %00000001 ' GPIO.0 A/D in, rest digital
ADCON0.7 = 1 ' Right justify for 10-bit
GPIO = %00000000 ' Initialize outputs
TRISIO = %101011 ' GPIO 0,1,3,5 = input, 2 & 4 outputs


Motor1 var gpio.2 ' H-Bridge pin 1
Motor2 var gpio.4 ' H-Bridge pin 2
SW1 VAR gpio.5 ' Door open limit switch


low sw1 ' Ensure limit switch is 0 (door is closed)
low Motor1 ' Turn off H-Bridge pin 1
low Motor2 ' Turn off H-Bridge pin 2
day=0 ' Initialise unit to check if day time

main:
if sw1=0 then day = 0 ' If limit switch is open, and mode is night then
adcin 0,number ' Read AN0
if day=0 then ' Day 0 = night, Day 1 = Day
If number >660 then ' If ACD result is above a threshold
low SW1 ' Set state of limit switch to off
high Motor1 ' Turn on H-Bridge pin 1
Low Motor2 ' Turn off H-Bridge pin 2
endif
endif
if SW1 = 1 then ' Door closes limit switch and applies 5v to GPIO.5
low Motor1 ' Turn off H-Bridge pin 1 } Stop motor
low Motor2 ' Turn off H-Bridge pin 2 }
day = 1 ' Set variable to day to indicate the door is open
endif

goto main


The logic behind this project is that when the light level increases at dawn past the threshold it drives the motor which by use of a threaded rod slides open the door on the coop. When the door closes a micro-switch at the end of the travel the power to the motor is turned off and the unit placed in day mode. At the end of the day a switch will be pressed directly applying 5v to pin2 of the H-Bridge thus reversing the motor, opening the door and opening the switch, changing its state from 1 to 0.

Any ideas ??

Malcolm

HenrikOlsson
- 21st January 2014, 16:10
Hi,
First you configure GPIO.5 as an input by setting the TRISIO.5=1 - OK, that's fine since you're going to be monitoring a switch connected to that pin.
Then you set up an alias so that SW1 accesses GPIO.5 - perfectly fine.
Then you go and do LOW SW1 - which turns the GPIO.5 into an output and pulls it low - not OK, the pin is no longer an input so it can't read the state of the switch.

Keep GPIO.5 as an input and make sure it has a pullup resistor to Vcc if the switch pulls it low or a pulldown resistor do Vss if the switch pulls it high.

/Henrik.

Scampy
- 21st January 2014, 16:47
Cheers Henrik,

I've removed all reference to SW1 =1 or LOW SW1 and it now no longer latches. - Thank you.

Now to actually turn this into a working door :)

Scampy
- 21st January 2014, 23:17
I've been playing about with the code and have now tested it on the development board over and over again, simulating the process of the door actuator being manually closed, and then opened triggered by the increasing light levels at dawn. Next step will be to transfer the PIC to a bit of strip board and add the regulators etc and then test it for real and monitor the current drawn to close the door on the coop. I plan on using a motorcycle battery 12v /4Ah which should be plenty. If funds permit I may add solar charging as a project at a later date.

Anyway, thanks guys for the assistance with this...

Malc

AvionicsMaster1
- 22nd January 2014, 21:04
I did a project similar to this and had to account for something blocking door travel. I ended up with .1 ohm, I think, in series with the motor to monitor load by measuring the voltage across the resistor to determine current flow.

If motor is free running then current will be high initially but should be lower once friction and inertia are overcome. But if it's blocked/hampered/whatever the stall current will stay relatively high. I think I set it up to try to open and if blocked wait some time and then try again. Another ADC input if you've got a free port. Just a thought.

Scampy
- 31st January 2014, 00:45
Well that version of the project didn't work so well in the field...

I'm now working on a second version which uses a RTC. Basically I already have half the code written for one of my other projects so most of this will be a cut and paste. But something is really puzzling me and would welcome your advice.

I'm using a 16F690 (20 pin DIP) because it has both a basic UART and IC2 interface, and I happened to have a sample in my project box. I could be cleaver (yeah right) and use the full capabilities of the DS1307 and program the times for each month so it takes care of BST and GMT etc, but for now I thought the easiest way would be to use a serial utility to set the time and trigger value as required. Using PicMultiCalc to get the coms values I am able to connect and receive data, however the time is shown as 00:00 in the following code. Now like I mentioned , I've cut and pasted the section and same variables in a previous project so there should be no reason for it not to work. To prove the DS1307 is working on the breadboard (it hasn't been removed since I took a break from the previous project) I removed the 16F690 and replaced it with the 18F4580 and connected the jumper to the EasyPIC5 board - clock was displaying the time set by the code. Noted the correct clk and dta pins, powered down the EP5 board and mapped the connections to the pins used by the 16F690. Replaced the 16F690 and tested again - the serial monitor in Microcode Studio connected and displayed "Time : 00:00"

I've looked at the data sheet, but not sure if I am missing anything (probably some register needs setting but I'll be dammed if I can see it) so hopefully someone here might be able to assist.

Here's the code



'************************************************* ***************
'* Name : Chicken Coop Door Control *
'* Author : Malcolm Crabbe *
'* Date : 30th January 2014 *
'* Version : 1.0 *
'* Notes : Uses PBP 2.60c *
'* : 16F690, int osc 4MHz *
'* : Program uses RTC to turn *
'* : on an electric motor and open a sliding door. *
'* : Door travel controlled by limit switches *
'************************************************* ***************


ASM
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF
endasm

ANSEL=%00000000
ADCON1=7
ADCON0 = %00000000 'AD converter module disabled
ADCON1 = %00001111

TRISA=%00000011 'set PORTA as all output
TRISC=%00000001 'set PORTC as all output apart from RC0
TRISB=%00000011

DEFINE HSER_RCSTA 90h 'Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h 'Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 25 '9600 Baud @ 0.16%
DEFINE HSER_CLROERR 1 'Clear overflow automatically

day var byte
RTCMin var byte 'RTC Minutes
RTCHour var byte 'RTC Hours
RTCsec var byte 'RTC Seconds

TimeH var byte 'variable to store Hours
TimeM var byte 'variable to store Minutes
SS VAR Byte 'variable to store Seconds

CounterA var byte 'General purpose Variable
CounterB var byte 'General purpose Variable

Counter1 var word 'used to store the current time as a digit. Counts minutes from 0000 at midnight (to be added later)

Relay var PortA.5 'used to activate relay and thus reverse direction
Motor var PortA.4 'used to drive the motor
SW1 VAR PortA.0 'Door open limit switch
SW2 VAR PortA.1 'Door closed limit switch
Tx var PortB.7 'used for sending time value in testing
Rx Var PortB.5 'used for receiving time value in testing

SetMN var byte 'Used to set time Minutes
SetHR var byte 'Used to set time Hours
SetSS var byte 'Used to set time Seconds

RCIF VAR PIR1.5 'USART receive flag
GIE VAR INTCON.7
RCIF=1

SCLpin var PORTB.6 'RTC pin - clk
SDApin var PORTB.4 'RTC pin - data

setHR = 08 'initial time to 8am
setMN = 00

'convert initial time to BDC and write it to the DS1307
CounterA=SetMN
Gosub ConvertBCD
RTCMin=CounterB

CounterA=SetHR
Gosub ConvertBCD
RTCHour=CounterB

I2Cwrite SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour]


test:

I2CREAD SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour] ; read DS1307 chip

timeH=(RTCHour>>4) 'convert the BCD format of the hours register and store in variable timeH
timeH=(timeH &$03)*10
timeH=timeH+(RTCHour&$0F)

timeM=(RTCMin>>4) 'convert the BCD format of the mins register and store in variable timeM
timeM=(timeM &$07)*10
timeM=timeM+(RTCMin&$0F)

ss=(RTCSec>>4) 'convert the BCD format of the sec register and store in variable ss
ss=(ss &$07)*10
ss=ss+(RTCSec&$0F)

Counter1 = (TimeH *60)+ TimeM 'take hours and multiply it by 60 then add odd minutes to get the total minutes into counter1

Hserout["Time: ",#TimeH DIG 1,#TimeH DIG 0,":",#TimeM DIG 1,#TimeM DIG 0,10]
pause 1000


goto test



'************************************************* ******************************
' convert BDC format to decimal
ConvertBCD:
CounterB=CounterA DIG 1 ' CounterA is the entry variable
CounterB=CounterB<<4 ' CounterB holds the converted BCD result on exit
CounterB=CounterB+CounterA DIG 0
Return
'************************************************* ******************************

AvionicsMaster1
- 31st January 2014, 01:49
Well, just the first part of the post I'm not sure what state you want ADCON1 set to. Initially you have it set to 7 then 15. That one extra bit appears to significantly effect your ADC conversion cycle.

I also think you need to set OSCCON and put a DEFINE OSC ? in your code. I know the default is 4MHz but isn't the RC oscillator in your config the low low frequency oscillator? Could be wrong about that without reading further.

TRISA is only 6 ports and I think PBP starts with the LSB so you'll have bits 0 and 1 as input. TRISB doesn't look to have RB0 to RB3 so only 4 bits needed to set as output. TRISIC is indeed 8 bits but you've got TRISIC.0 set to input not as described in comments.

I don't often do serial so you'll have to let someone else chime in. I didn't look at rest of code. Hopefully I'm correct on at least one of these items and it will solve your problem.

Scampy
- 31st January 2014, 09:43
Thanks for the assistance

I've just sat down with a large mug of coffee and some toast and run through the datasheet... I think I've covered most things (I still find these datasheets a struggle, but hopefully picking things up). I've set the registers as follows (with comments), and the code compiles



ASM
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF
endasm

DEFINE OSC 4
DEFINE HSER_RCSTA 90h 'Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h 'Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 25 '9600 Baud @ 0.16%
DEFINE HSER_CLROERR 1 'Clear overflow automatically

ANSEL = %00000000 'Set all pins digital
ANSELH = %00000000 'Set all pins digital
ADCON0 = %00000000 'AD converter module disabled
OSCCON = %01100101 'bit7 not used, bits 6-4 4mhz default, bit3 int osc, bit2 HS stable (ignored - at 4Mhz), bit1 not stable, bit0 int osc used for system clk
CCP1CON= %00000000 'Turn off CCP module
SSPCON = %00001011 'Ic2 master

TRISA=%00000011 'set PORTA as all output apart from RA0 and RA1( bits 7&8 unimplimented read as 0)
TRISB=%11110000 'set PORTB as all input ( bits 0-3 unimplimented read as 0)
TRISC=%11111111 'set PORTC as all input (default for POR)


Having compiled and loaded the code, pleased to say it all works now !!

OK I might of gone overboard on configuring registers, but at least it's helped me get some understanding with the datasheets.

HenrikOlsson
- 31st January 2014, 10:27
Hi,
Glad you've got it going! Just a quick note: The I2CREAD/I2CWRITE commands does not use the (M)SSP module in the PIC. You're enabling the (M)SSP module for I2C mode so I'm actually a bit surprised that it works because I thought that when enabled it (the (M)SSP module) takes control over the I/O-pins - I'm obviously mistaken there.

However, the PBP I2C commands are bitbanged, they don't use the I2C hardware in the PIC so there's no need to enable the hardware for it. It might lead to problems.

/Henrik.

Scampy
- 31st January 2014, 10:55
Thanks Henrik,

So I can remove the SSPCON line ?

HenrikOlsson
- 31st January 2014, 11:27
Yes, according to the datasheet the POR default of the SSPCON register is 0. Looking at the register definition it shows that as long as bit 5 is 0 the SSP module is disabled and its pins functions as normal I/O. This is probably also why it works the way you currently have it - you do have it configured for I2C mode but it's not actually enabled since bit 5 is cleared. Had you enabled it I don't think the I2C commands would've worked since the SSP module then would've been in control of the pins.

/Henrik.

Scampy
- 31st January 2014, 16:25
Guys,

I've been resting my code using a DC motor driven by a simple transistor circuit as per attached which works well, with the intention of using a double pole change over relay to switch the polarity to the motor (throw off from my old model railway days as that's how we used to make the loco go backwards or forwards). The think is I can't get my head round how to use the transistor to turn the power on / off.

I came up with the attached, but not sure if this would work, or if I should have the transistor between the relay and GND (ie C to relay, E to GND). I've left the Diode out as the motor is bi-directional

Advice welcome before I blow up a handful of transistors trying :)

pedja089
- 31st January 2014, 18:28
I use this for motor driver:
7212

Scampy
- 31st January 2014, 19:31
Thanks you..

HenrikOlsson
- 31st January 2014, 20:03
Hi,
Regarding your first schematic, generally you need to put the transistor on the low side. Otherwise you need a higher voltage on the base than you've got on the collector. Put the relay "on top", then on to the motor and finally the transistor at the bottom, emitter to ground. Yes, the motor is biderectional but the current thru the transistor is always the same so put the diode back across is, cathode facing "up" of course.

/Henrik.

Scampy
- 3rd February 2014, 16:14
Quick questions guys, I've been developing the hardware further and need to swap the 2930 transistor for something more powerful for driving the 540 type motor. I have a TIP126 PNP darlington, which works, but with reverse logic on the base. IE instead of turning on when the base is high it's high when the pic pin is low. I could change the code so that the output is constantly high and goes low when the conditions are met, but was wondering if there was a simple way of making the transistor fire with a positive voltage on its base ?

Demon
- 3rd February 2014, 17:22
If you don't want to change your code, what if you add a small NPN transistor to the base of the PNP?

Connect the NPN to GND instead of VDD (all sounds plausible in my head).

Robert

pedja089
- 3rd February 2014, 17:30
Please delete this post

Scampy
- 3rd February 2014, 17:41
Rob,

I'll opt for changing the code... it's only a matter of changing half a dozen lines from how to high :)

But thanks for the input

HenrikOlsson
- 3rd February 2014, 17:54
Yeah, there's no way to change the actual transistor (obviously) so what you need to do is invert the signal which you can do by adding a NPN transistor "in front" of the PNP like Robert says.

Previously I said to put the transistor on the low side but that was when you used a NPN transistor. Now, with a PNP "serviced" by a NPN you'll be better of putting on the high side. It will work with the PNP on the low side as well but only as long the voltage feeding the motor isn't higher than the voltage used to drive the transistors (ie the voltage feeding the PIC) + around 1V for a Darlington. Also, remember that the voltage drop across a Darlington transistor is higher than across a "normal" BJT.

You need to remember that ordinary transistors (BJTs or Bipolar Junction Transistor) are operating on current. Ie, for a NPN transistor we push a certain current into the base which gets "amplified" by the gain of the transistor and "pulled down into" the collector. The base basically behaves as diode connected to the emitter so there will be a voltage drop across it of ~0.6V (for a silicon device) as with any diode. So, IF you put a NPN transistor on the high side of the load with the collector connected to, say 12V, you basically need a voltage of 12.6V in order to be able to "push" current into the base. If you try to push current into the base using 5V the transistor will only partly open (ie it'll operate in its linear region) and it'll disipate a lot of heat. This is what's done in linear amplifiers etc but not what you want when using the transistor as a switch.

OK, so what if we put that NPN on the low side of the load (motor). Now, the emitter is connected to ground so there's plenty of headroom in using 5V to push current into the base and it'll work just fine provided you use a sensible value for the base resistor.

Then you decide to change to a PNP transistor.....
The PNP transistor is "operated" by "pulling" a current out thru the base (as oposed to driving current into the base for a NPN). So, if you put the PNP on the low side of the load its emitter (which is now connected to the load) will "see" the full supply voltage when the transistor is OFF. So, in order to keep the transistor OFF no current can be allowed to flow down thru its emitter and out of the base, right? In order to prevent that from happening the voltage at the base needs to be atleast the same as the voltage feeding the load less one diode drop (or two for a Darlington). If the powersupply voltage is 12V and you're driving that low side PNP with 5V from a PIC it will never turn off completely.

Putting your Darlington PNP on the high side of the load with a small NPN to "pull" current thru the Darlingtons base to ground (thru a resistor of course) is the right way to do it given those particular circumstances.

/Henrik.

Scampy
- 3rd February 2014, 19:19
Henrik,

Thanks for the explanation. And yes I did find the motor would not actually stop running, it would shut off, then slowly start up again, gradually increasing in speed.

If I've followed your post correctly, and followed the schematic provided by Pedja, would the attached work (using say a 2n3904 and a 1K base resistor) - Note that the motor supply is using 6v with the PIC running at 5v (and I've noticed I've omitted the diode across the relay -Doh !)

AvionicsMaster1
- 3rd February 2014, 19:30
Wow. Great explanation Henrik. It answered a few questions I'd been having with a project. Thanks for taking the time.

HenrikOlsson
- 3rd February 2014, 19:54
Scampy,
You have the Darlington PNP upside down, the emitter needs to go to the positive rail. And you need a resistor in the Darlingtons base as well. If you don't put a resistor there you'll basically short out the supply with the base emitter diode(s) in the Darlington - not good. Use 1k or whatever.

EDIT: Oh, and the emitter of the small NPN must go to ground - not to the collector of the Darlington.

AvionicsMaster1,
Thanks, and you're welcome! Perhaps not the best explaination from a purely technical standpoint but never the less.... :-)

/Henrik.

Scampy
- 3rd February 2014, 20:17
Henrik, Thanks for the info.

I was browsing through my old posts as I recall I did something similar for a model train controller... only this time I used two transistors in a darlington pair. I'll use this as a basis for the output to the motor - via the relay contacts

dw_picbasic
- 8th February 2014, 15:29
I have ever used a DPDT relay as a motor direction control instead of an H bridge device.
In some cases the relay takes care of a lot of H-bridge current limitation issues since there is negligible resistance in relay contacts. A 2n7000 mosfet can a drive large number of different relay types nicely.

And the relay only requires one control pin from the PIC.
If speed control is needed, I use a mosfet to pulse current to the motor.

Fun stuff!! :-]

Scampy
- 11th February 2014, 14:51
I've just transferred the project from the development board to stripboard. The circuit is running fine in that the RTC is being read and serial comms are working, however the PIC is not driving the relays hard enough to move the contacts (although they can be heard clicking slightly). I've changed the base resistor as I'm now using 5v DIL relays with contacts rated at 2A 30v which should be OK for driving a 6v motor that draws 700mA under load. In the attached circuit R1 is 100 ohm, Q1 is a BC639 NPN and the relay coil has a resistance of 63 ohms. I've also found that when the PIC makes the pin high it's reaching 2.84v and not 5v or near as dammit. Any suggestions ?

HenrikOlsson
- 11th February 2014, 15:17
Hi,

In the datasheet I looked at the current gain for the BC639 is stated as minimum 40. Your relay coil needs 5V/63ohm=80mA at 5V, with a gain of 40 you need to push 80/40=2mA into the base of the transistor.

There's a drop of 0.6V across the base-emitter junction so if the PIC is powered with 5V you're left with ~4.4V to do it. The base resistor then needs to be 4.4/0.002=2200ohm, I'd go with half that or ~1k.

With a 100ohm base resistor you're overloading the output drivers in the PIC, trying to pull ~44mA from an output rated at 20mA. This is probably why the voltage is clamped to way less than 5V.

Fit a 1k-2k resistor then verify the operation in steps.
1) Measure the voltage at the PIC output, it should be either 0 or 5V (or close to it). If it's not then something is wrong.
2) Measure the voltage at the base of transistor, it should be either 0 or 0.6V (or close to it). If it's not something is wrong.
3) Measure the voltage at the collector of the transistor, it should be 5V when the transitor is OFF and close to 0 when the transitor is ON.

If it doesn't work please do the above measurments and report the results.

/Henrik.

LinkMTech
- 11th February 2014, 15:29
The output drive is current limited to 25mA meaning an internal resistance of about 200 Ohms at 5V. That's why you see the 2.84V at the pin and nothing close to 5V.
7242


Also, I would think you only need about a 2K Ohm resistor to drive the NPN that has a min. gain of 40 to drive the 80mA relay load.

Scampy
- 11th February 2014, 15:44
LOL - I originally had a 1K base resistor in there and though that was limiting the current / voltage !

The data sheet on the relay does indeed state a current draw of 80ma at 5v - I'll replace the base resistors with 1.5K, being midway between the 1K recommendation and 2K calculated, then follow Henrik's test and I'll report back

Scampy
- 11th February 2014, 19:27
Fit a 1k-2k resistor then verify the operation in steps.
1) Measure the voltage at the PIC output, it should be either 0 or 5V (or close to it). If it's not then something is wrong.
2) Measure the voltage at the base of transistor, it should be either 0 or 0.6V (or close to it). If it's not something is wrong.
3) Measure the voltage at the collector of the transistor, it should be 5V when the transitor is OFF and close to 0 when the transitor is ON.

If it doesn't work please do the above measurments and report the results.

/Henrik.

Fitted a 1.5K resistor

1) - Voltage out when the pin goes high = 4.52v
2) - Base of transistor voltage measured 0.73v
3) - Voltage at collector when PIC pin was HIGH was 0.03v and 5.01v when PIC pin was LOW

Still the relay contacts didn't switch.

Thinking it might be the regulator as I'm using a 200mA version of the 7805 I changed this for a traditional 1 amp version - still no change.

As the new relays are DIL footprint (16 pin DIL) and I am using sockets, I removed the relays and inserted the pins of the original relay into the contacts on the DIL socket. This relay also has a coil of 68 ohms so would be drawing similar current of around 80mA ? - The contacts changed over just fine. Last test was to attach two wires to the coil and plug this into the DIL socket - still no change, but plugging the coil directly across the 5v switched it hard...

I'm going to re-breadboard the hardware with the DIL relays and see if it switches OK just to rule out a fault on the stripboard (my eyes are not what they used to be - so I could have a dry joint or short somewhere !) - but I don't hold up much hope as any such issues should of resulted in the same thing happening with the original relay when tested with the stripboard.....

Scampy
- 11th February 2014, 20:51
Its now working.

I removed all the links to the relays apart from the coils - tested and it appeared to energise. I then googled the datasheet for the relays and found that the contacts where wired differently to the other relay (NO / NC then the comm rather then NO / comm / NC) - rewired the stripboard (now quite a mess) and it works (well I get 5v out to the motor when the pic energises the relays :) )

Thanks to all who contributed - and I'll note that formula for working out the resistances - Cheers Henrik

Scampy
- 11th February 2014, 23:19
Well for reference and to aid anyone who may stumble across this thread in future here's the circuit diagram and final code (full of comments to explain how it works)



'************************************************* ***************
'* Name : Chicken Coop Door Control *
'* Author : Malcolm Crabbe *
'* Date : 30th January 2014 *
'* Version : 1.0 *
'* Notes : Uses PBP 2.60c *
'* : 16F690, int osc 4MHz *
'* : Program uses RTC to turn *
'* : on an electric motor and open a sliding door. *
'* : Door travel controlled by limit switches *
'************************************************* ***************


ASM
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF
endasm

DEFINE OSC 4
DEFINE HSER_RCSTA 90h 'Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h 'Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 25 '9600 Baud @ 0.16%
DEFINE HSER_CLROERR 1 'Clear overflow automatically

ANSEL = %00000000 'Set all pins digital
ANSELH = %00000000 'Set all pins digital
ADCON0 = %00000000 'AD converter module disabled
OSCCON = %01100101 'bit7 not used, bits 6-4 4mhz default, bit3 int osc, bit2 HS stable (ignored - at 4Mhz), bit1 not stable, bit0 int osc used for system clk
CCP1CON= %00000000 'Turn off CCP module
SSPCON = %00001011 'Ic2 master

TRISA=%00000111 'set PORTA as all output apart from RA0, RA1 and RA2( bits 7&8 unimplimented read as 0)
TRISB=%11110000 'set PORTB as all input ( bits 0-3 unimplimented read as 0)
TRISC=%11111111 'set PORTC as all input (default for POR)

day var byte
RTCMin var byte 'RTC Minutes
RTCHour var byte 'RTC Hours
RTCsec var byte 'RTC Seconds

TimeH var byte 'variable to store Hours
TimeM var byte 'variable to store Minutes
SS VAR Byte 'variable to store Seconds

CounterA var byte 'General purpose Variable
CounterB var byte 'General purpose Variable
TempWD VAR WORD

Counter1 var word 'used to store the current time as a digit. Counts minutes from 0000 at midnight

Char var byte

Relay var PortA.5 'used to activate relay and thus reverse direction
Motor var PortA.4 'used to drive the motor
SW1 VAR PortA.0 'Door open limit switch
SW2 VAR PortA.1 'Door closed limit switch
SW3 var PortA.2 'Manual close button
Tx var PortB.7 'used for sending time value in testing
Rx Var PortB.5 'used for receiveing time value in testing

SetMN var byte 'Used to set time Minutes
SetHR var byte 'Used to set time Hours
SetSS var byte 'Used to set time Seconds

onHR var byte 'Used to set the Opening time (Hrs)
onMN var byte 'Used to set the Opening time (Min)
Ontime var word 'On time value in minutes

RCIF VAR PIR1.5 'USART receive flag
GIE VAR INTCON.7
RCIF=1

SCLpin var PORTB.6 'RTC pin - clk
SDApin var PORTB.4 'RTC pin - data

setHR = 06 'On powerup time set to 00 Hrs
setMN = 44 'On powerup time set to 00 minutes

onHR = 06
onMN = 46

CounterA=SetMN 'convert initial time to BDC and write it to the DS1307
Gosub ConvertBCD
RTCMin=CounterB

CounterA=SetHR
Gosub ConvertBCD
RTCHour=CounterB

I2Cwrite SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour]
day=0 ' set mode to night
low Motor ' set motor to off
low relay ' relay off


'************************************************* ******************************
Main:
'************************************************* ******************************

I2CREAD SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour] ; read DS1307 chip

timeH=(RTCHour>>4) 'convert the BCD format of the hours register and store in variable timeH
timeH=(timeH &$03)*10
timeH=timeH+(RTCHour&$0F)

timeM=(RTCMin>>4) 'convert the BCD format of the mins register and store in variable timeM
timeM=(timeM &$07)*10
timeM=timeM+(RTCMin&$0F)

ss=(RTCSec>>4) 'convert the BCD format of the sec register and store in variable ss
ss=(ss &$07)*10
ss=ss+(RTCSec&$0F)

Counter1 = (TimeH *60)+ TimeM 'take hours and multiply it by 60 then add odd minutes to get the total minutes into counter1
Ontime = (onHR*60)+onMN

Hserout["Time: ",#TimeH DIG 1,#TimeH DIG 0,":",#TimeM DIG 1,#TimeM DIG 0,":",#ss DIG 1,#ss DIG 0," Counter = ",#counter1," Ontime = ",#ontime,13,10]
pause 200
FOR TempWD = 0 TO 1000
IF RCIF THEN GOto comms ' Check to see if there is communications on the comm port
PauseUs 1000
NEXT TempWD

if counter1 = ontime and SW2=1 then ' If counter matches on time and A.1 is high then
high Motor ' Turn on the motor
high relay ' Energise the relay
endif

if SW1 = 1 then ' Door open limit switch (A.0) hit and applies 5v to pin
low Motor ' Stop motor
low relay ' de-energise relay
endif

if ontime < counter1 or ontime > counter1 then ' If the counter is anything other than ontime, turn everything off
low SW1
low motor ' Turn on the motor
low relay ' Relay kept off for reverse polarity of motor
endif

If SW3 = 1 then
high motor
low relay
Low SW1
endif

if SW2 = 1 and ontime < counter1 or ontime > counter1 then ' Door closed limit switch hit and applies 5v to pin
low Motor ' Stop motor
endif

goto Main
'************************************************* ******************************
'************************************************* ******************************
convert:
CounterA=SetMN
Gosub ConvertBCD
RTCMin=CounterB

CounterA=SetHR
Gosub ConvertBCD
RTCHour=CounterB

I2Cwrite SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour]
return
'************************************************* ******************************
comms:
HSERIN [Char]
SELECT CASE Char
CASE "T","t" ' set time
hserout ["Set Time Hour ",10]
HSERIN [#setHR]
hserout ["Set Time minutes ",10]
HSERIN [#setMN]
gosub convert

CASE "O","o"
Hserout["Set Open Time: ",13,10]
hserout ["Set Hour ",10]
HSERIN [#onHR]
hserout ["Set Minutes ",10]
HSERIN [#onMN]
Ontime = (onHR*60)+onMN

CASE "C","c"
Hserout["Time: ",#TimeH DIG 1,#TimeH DIG 0,":",#TimeM DIG 1,#TimeM DIG 0," Counter = ",#counter1,13,10]
pause 500
end select
goto Main

'************************************************* ******************************
' convert BDC format to decimal
ConvertBCD:
CounterB=CounterA DIG 1 ' CounterA is the entry variable
CounterB=CounterB<<4 ' CounterB holds the converted BCD result on exit
CounterB=CounterB+CounterA DIG 0
Return
'************************************************* ******************************


Ok the code may be very basic, could possibly be written tighter and isn't really rocket science, but it works for me. Likewise the choice of transistor in the schematic might of been better, but it's what I had and after the debuging - works with the relays etc.

I would like to thank all those who contributed to this thread and not only provided the support I needed, but also educated me both in PicBasic Pro and electronic component selection. - Thanks guys

Disclaimer:
The usual disclaimer applies, ie I accept no responsibility what-so-ever - anyone uses this code / schematic at their own risk etc etc... lardy dar de dar !! :) -- (sorry to high on pain killers for tooth ache !!)

dw_picbasic
- 12th February 2014, 00:29
Just for the fun of it, you may consider playing around with the relay and transistor separate from the PIC. There may be some possibility that a base bias resistor between 5k to 10K may actually switch that relay quite nicely. If so, that would put even less current demand on the output of the PIC. In the future if you are browsing a supplier like allelectronics, look for the 2n7000 N-Channel mosfet. It can handle 400mA and won't require any current at all from a PIC, since it is voltage driven. Just a 1 meg bias resistor holding the gate to ground. I bought a surplus box-of-em on ebay a while ago. Enough to last me the rest of my life ;-D

Great pics my friend!! and a very well done project!!
Congrats!!
Duane :-]