PDA

View Full Version : USB issue - 18F4550



Scampy
- 15th February 2013, 23:59
Hi Guys,

need some advice as I'm going crazy trying to figure out what I've screwed up in the code I'm using.

A good friend of mine wrote a very basic project to control some aquarium lights. His code basically uses four CASE statements per channel to set the on time for channel 1 & 2, the ramp up time for each channel, the duration both channels are on, and the fade down duration. So for example channel one could come on at 10:00, channel two on at 10:15, both then fade up to full brightness by 11:00, channel one then begin to fade down at 20:00, turning off at 21:00, with channel two fading between 20:30 and 22:00 for example. That part works fine.

To make life easy my friend wrote a small windows application so that the on / off, fade durations etc could all be set by sliders and then the values squirted to the chip, which was originally an 18f2550. As I need more pins as I am developing his project further (with his permission) I've opted for an 18F4550. I was originally using a 20Mhz Xtal and with the following settings



ASM ; 18F2550/4550, 20mhz crystal
__CONFIG _CONFIG1L, _PLLDIV_5_1L & _CPUDIV_OSC1_PLL2_1L & _USBDIV_2_1L
__CONFIG _CONFIG1H, _FOSC_HSPLL_HS_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_OFF_2L & _VREGEN_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM
DEFINE OSC 48
CLEAR


The PC picks up the connection and the USB device was reported as being installed successfully. His application loads, and automatically reads the values from the PICs eprom settings and moves the sliders and displays the numbers as per the default values that are entered. However, if the sliders are changed and the "update" button is pressed the new values are not written back to the chip.

The code uses DT_HID260 which I'm guessing is something written by Darrel.



'************************************************* ***************
'Setup Interrupts
'************************************************* ***************
INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler USB_Handler
INT_Handler TMR1_INT, _MyTimer, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
endasm
T1CON = %10000001 ; free-running, 1:1 prescaler
@ INT_ENABLE TMR1_INT ; enable Timer1 interrupts

'************************************************* ***************
'Setup USB
'************************************************* ***************
INCLUDE "DT_HID260.pbp"

DEFINE USB_VENDORID 6017
DEFINE USB_PRODUCTID 1969
DEFINE USB_VERSION 1
DEFINE USB_VENDORNAME "CSL Designs"
DEFINE USB_PRODUCTNAME "Aqua-LED"
DEFINE USB_SERIAL "001"
DEFINE USB_INSIZE 64 ; IN report is PIC to PC (8,16,32,64)
DEFINE USB_OUTSIZE 64 ; OUT report is PC to PIC
DEFINE USB_POLLIN 10 ; Polling times in mS, MIN=1 MAX=10
DEFINE USB_POLLOUT 10

'************************************************* ***************


The actual bit that gets called to do the USB comms is



SendUSB:
for i = 0 to USBBufferCount - 1
read i,USBTXBuffer[i] 'Read the eeprom data and store in the outward bound buffer
next i
SendData:
USBOut 1, USBTXBuffer, USBBufferCount , SendDATA ' if bus available, transmit data
return

GetUSB:
USBin 1, USBRXBuffer, USBBufferCount, Timeout ' if bus available, receive data
if Firstsend = 0 then
for i = 0 to USBBufferCount - 1
write i,USBRXBuffer[i] 'Write the eeprom data received from the PC
next i
gosub Read_eeprom 'Read eeprom data into the variables
else
Firstsend = 0
endif
Timeout:
return

' If USB plugged display USB on the display
USB_Plugged:
if plugged = 0 then
lcdout $FE,$91," "
else
lcdout $FE,$91,"USB"
endif
return


I've tried removing the timeout option and substituting it for the getUSB so it loops and that didin't work, I've also tried using a 4Mhz resonator with the same fuse settings as the 2550 chip and that still fails to update



ASM
__CONFIG _CONFIG1L, _PLLDIV_1_1L & _CPUDIV_OSC1_PLL2_1L & _USBDIV_2_1L
; ; ; USB clock source comes from the 96 MHz PLL divided by 2
; ; [OSC1/OSC2 Src: /1][96 MHz PLL Src: /2]
; No prescale (4 MHz oscillator input drives PLL directly)


__CONFIG _CONFIG1H, _FOSC_XTPLL_XT_1H & _IESO_OFF_1H
; ; ; Oscillator Switchover mode disabled
; ; Fail-Safe Clock Monitor disabled
; XT oscillator, PLL enabled, XT used by USB

__CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_ON_2L & _BORV_2_2L & _VREGEN_ON_2L
__CONFIG _CONFIG2H, _WDT_OFF_2H
__CONFIG _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H & _CCP2MX_ON_3H
__CONFIG _CONFIG4L, _STVREN_ON_4L & _LVP_OFF_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
endasm
DEFINE OSC 48
clear


I've also checked the settings for PORT.C to make sure it's not all set to output - still no joy.

I would welcome suggestions on things to try, or point me to where the problem may be.... My friend thinks it must be a timing issue, which when I was running with a 20 Mhz and a divide/5 prescaler I might of agreed (however I would of thought that if this was the case then windows would of reported a device not recognised error), but then even using the 4Mhz resonator (which doesn't seem to make the code run any slower, so I would be happy with that for the performance) still didn't work.

Thanks in advance...

Malcolm

Scampy
- 16th February 2013, 00:23
Edit. I noticed this in the code


if RX_READY = 1 and plugged = 1 then gosub GetUSB


So using the LCD to debug I've found RX_READY is 0 when the cable is connected and the application on the PC running - Looking at the DT_HID260 code, this variable is set within that code --- DT help !!! :)

Darrel Taylor
- 17th February 2013, 19:21
Hi Malcolm,

I'm affraid there's not enough code posted to be able to find your problem.
I think what you've posted is the part you've gone over a hundred times and couldn't see anything wrong. So maybe there's nothing wrong there.
It's likely the problem is somewhere else.

The RX_READY bit is simply copied from the Hardware USB status register on every USB interrupt.
If it never goes high, then either nothing is being sent from the PC, or the data has been collected already before you displayed RX_READY on the LCD.
I would suggest enabling the USB Status LED's so you can see what's happening in real time.


; --- Each USB LED is optional, comment them if not used ----
DEFINE USB_LEDPOLARITY 1 ; LED ON State [0 or 1] (default = 1)
DEFINE USB_PLUGGEDLED PORTB,0 ; LED indicates if USB is connected
DEFINE USB_TXLED PORTC,2 ; " " data being sent to PC
DEFINE USB_RXLED PORTC,1 ; " " data being received from PC

Scampy
- 18th February 2013, 00:35
Hi Darrel,

Here's the full code, which I hope might help. I have tried a USB scanner and got the attached results.. which mean nothing to me, other than it throws up some errors when the PC software was launched.



@ errorlevel -205

'************************************************* ***************
' Config settings
'************************************************* ***************

asm

; 18F2550/4550, 20mhz crystal
__CONFIG _CONFIG1L, _PLLDIV_5_1L & _CPUDIV_OSC1_PLL2_1L & _USBDIV_2_1L
__CONFIG _CONFIG1H, _FOSC_HSPLL_HS_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_OFF_2L & _VREGEN_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM
DEFINE OSC 48
CLEAR


'************************************************* ***************

ADCON0 = 0 'Set ADCON0
ADCON1 = %00001111 'Set D i/o
CMCON = 7 'Disable Comparators
CCP1CON = %00001100 'set pwm white - pin12
CCP2CON = %00001100 'set pwm blue - pin12
TRISA = %00000000 'set PORTA as all output
TRISB = %00000011 'set PORTB as all output
TRISC = %01011000 'set PORTC as all output apart from port 6 used for backlight button
PR2 = 249
'T2CON = %00000100 ' Start Timer2, Prescaller 1:1
'************************************************* ***************

DEFINE LCD_DREG PORTB ' Setup the ports for the LCD (as not set to the default layout as set in PBP)
DEFINE LCD_DBIT 0 ' Set starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_RSREG PORTB ' Set LCD Register Select port
DEFINE LCD_RSBIT 4 ' Set LCD Register Select bit
DEFINE LCD_EREG PORTB ' Set LCD Enable port
DEFINE LCD_EBIT 5 ' Set LCD Enable bit
DEFINE LCD_BITS 4 ' Set LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' Set number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Set command delay time in us
DEFINE LCD_DATAUS 50 ' Set data delay time in us
'************************************************* ***************
LCD_BACKLIGHT var PORTB.7 'Set port b .7 for LCD backlight (High = on)
PBUTTON var PORTC.6 'set PORTC.6 for the button for the lcd
SDA_Pin var PORTB.0 'RTC SDA Data pin
SCL_Pin var PORTB.1 'RTC SCL clock pin

CounterA var byte ' General purpose Variable
CounterB var byte ' General purpose Variable
option var byte
H_butt VAR PORTE.2
M_butt VAR PORTE.0
S_butt VAR PORTE.1

'************************************************* ***************
i var word 'Misc counter
iv var word
LCD_Mode var word 'LCD light mode
LCD_Timer var word 'Timer for how long the LCD is on for.
LCD_Time var word 'Counter for the timer
LCD_Tmr var word

'************************************************* ***************
' Temp probes
Temperature var word[4]

Temperature1 var temperature[0]
Temperature2 var Temperature[1]
Temperature3 var Temperature[2]
Temperature4 var Temperature[3]

'************************************************* ***************
' RTC Variables


'RTC_Msecs var byte
RTC_Secs var byte
RTC_Mins var byte
RTC_Hours var byte
RTC_Day var byte
RTC_WDay var byte
RTC_Month var byte
RTC_Year var byte
RTC_Ctrl var byte
dummy var byte
RTclock var byte[8]
Tick_Tmr var byte

SetupPreset:
RTC_Secs=$00 ' Seconds preset to 00
RTC_Mins=$59 ' Minutes preset
RTC_Hours=$09 ' Hours preset
RTC_WDay=$01 ' Weekday preset to 01
RTC_Day=$12 ' Day preset 12
RTC_Month=$06 ' Months preset to June
RTC_Year=$02 ' Year preset to 2002
RTC_Ctrl=$10

'************************************************* ***************
' LED variables
' Whites:
W_Min var word 'Min Light value
W_Max var word 'Max Light value
W_Fade_In var word 'Fade in duration
W_Fade_Out var word 'Fade out duration
W_On_Time_H var word 'What time to turn the lights on
W_On_Time_M var word 'What time to turn the lights on
W_Off_Time_H var word 'Time to turn lights off
W_Off_Time_M var word 'Time to turn lights off

' Blues:
B_Min var word 'Min Light value
B_Max var word 'Max Light value
B_Fade_In var word 'Fade in duration
B_Fade_Out var word 'Fade out duration
B_On_Time_H var word 'What time to turn the lights on
B_On_Time_M var word 'What time to turn the lights on
B_Off_Time_H var word 'Time to turn lights off
B_Off_Time_M var word 'Time to turn lights off

'Running fade variables
B_FadeIn_Time var word 'LIVE fade delay time seconds
B_FadeOut_Time var word
W_FadeIn_Time var word
W_FadeOut_Time var word
B_Cnt var word 'Seconds counter for the timing of adjusting the PWM
W_Cnt var word
B_Tick var word
W_Tick var word

'PWM Variables where the current output values are stored
W_PWM var word 'Whites
B_PWM var word 'Royal Blues

'************************************************* ***************
Blue_Day_Cycle var word 'Store for which part of the day cycle we are in
White_Day_Cycle var word

' Constants for the current running mode cycle for the lights
DAWN con 0
DAY con 1
DUSK con 2
NIGHT con 3

'************************************************* ***************
'Expendable variables used for misc calculations etc
Vb_1 var word
Vb_2 Var word
Vb_3 var word
Vb_4 var word

'************************************************* ***************
USBBufferCount Var Byte

Firstsend var byte ' When first connected the pc auto sends data, but we want to READ first otherwise
' the eeprom gets overwritten with zeros as the pc sends a packet we DONT want.
'************************************************* ***************
' Set default data in internal EEPROM

data @0
data 10 'Whites ON Time HOURS
data 00 'Whites ON Time MINS
data 10 'Whites OFF Time HOURS
data 10 'Whites OFF Time MINS
data 0 'Whites Fade IN duration HOURS
data 5 'Whites Fade IN duration MINS
data 0 'Whites Fade OUT duration HOURS
data 3 'Whites Fade OUT duration MINS
data 0 'Whites MIN Intensity %
data 100 'Whites MAX Intensity %

data 10 'Blues ON Time HOURS
data 0 'Blues ON Time MINS
data 10 'Blues OFF Time HOURS
data 10 'Blues OFF Time MINS
data 0 'Blues Fade IN duration HOURS
data 5 'Blues Fade IN duration MINS
data 0 'Blues Fade OUT duration HOURS
data 5 'Blues Fade OUT duration MINS
data 0 'Blues MIN Intensity %
data 100 'Blues MAX Intensity %

Data @150,74,97,110,70,101,98,77,97,114,65,112,114
' Jan Feb Mar Apr
Data 77,97,121,74,117,110,74,117,108,65,117,103
' May Jun Jul Aug
Data 83,101,112,79,99,116,78,111,118,68,101,99
' Sep Oct Nov Dec
Data 84,117,101,87,101,100,84,104,117,70,114,105
' Tue Wed Thu Fri
Data 83,97,116,83,117,110,77,111,110
' Sat Sun Mon

'************************************************* ***************
'Setup Interrupts
'************************************************* ***************
INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler USB_Handler
INT_Handler TMR1_INT, _MyTimer, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
endasm
T1CON = %10000001 ; free-running, 1:1 prescaler
@ INT_ENABLE TMR1_INT ; enable Timer1 interrupts

'************************************************* ***************
'Setup USB
'************************************************* ***************
INCLUDE "DT_HID260.pbp"

DEFINE USB_VENDORID 6017
DEFINE USB_PRODUCTID 1969
DEFINE USB_VERSION 1
DEFINE USB_VENDORNAME "CSL Designs"
DEFINE USB_PRODUCTNAME "Aqua-LED"
DEFINE USB_SERIAL "001"
DEFINE USB_INSIZE 64 ; IN report is PIC to PC (8,16,32,64)
DEFINE USB_OUTSIZE 64 ; OUT report is PC to PIC
DEFINE USB_POLLIN 10 ; Polling times in mS, MIN=1 MAX=10
DEFINE USB_POLLOUT 10

'************************************************* ***************
' Start the program
'************************************************* ***************
code_start:
' i2cwrite SDA_Pin,scl_pin,$D0,$00,[$00,$00,$00,$59,$19,$24,$08,$00]
I2Cwrite SDA_pin,SCL_pin,$D0,$00,[RTC_Secs,RTC_Mins,RTC_Hours,RTC_WDay,RTC_Day,RTC_M onth,RTC_Year,RTC_Ctrl]
Blue_Day_Cycle = DAWN
White_Day_Cycle = DAWN
b_cnt = 0
w_cnt = 0

gosub read_eeprom 'Read in the data needed for the lighting periods

Firstsend = 1
USBBufferCount = 64 'Size of the USB buffer we use

LCD_Mode = 3 'LCD Backlight always ON
LCD_Time = 0 'Both these are used for the duration the backlight
LCD_Tmr = 0 'is on when not in mode 3.

gosub Calc_Fade

high LCD_BACKLIGHT

LCDOUT $FE,1
' Display splash screen

lcdout $FE,$C0," AquaLED V1.0 "
lcdout $FE,$94," (C)2010 M.Jervis "
pause 1000 'wait a seconds so they can see it
lcdout $FE,1 'Clear the screen



'************************************************* ***************
'Main program loop
'************************************************* ***************
main:
'Main body of program where we determine which time of day we are in



'*** Do BLUE daily cycle
select case Blue_Day_Cycle
case DAWN
lcdout $FE,$94,"BL: DAWN "
if b_cnt = B_Fadein_time and B_PWM < B_Max then
B_PWM = B_PWM + 1
b_cnt = 0
endif
if B_PWM = b_max then
Blue_Day_Cycle = DAY
endif
case DAY
lcdout $FE,$94,"BL: DAY "
if RTC_Hours = B_Off_Time_H and RTC_Mins = B_Off_Time_M then
Blue_Day_Cycle = DUSK
b_cnt = 0
endif
CASE DUSK
lcdout $FE,$94,"BL: DUSK "
if b_cnt >= B_Fadeout_time and B_PWM > B_Min then
B_PWM = B_PWM - 1
b_cnt = 0
endif
if B_PWM = b_min then
Blue_Day_Cycle = NIGHT
endif
case NIGHT
lcdout $FE,$94,"BL: NIGHT"
if RTC_Hours = B_On_Time_H and RTC_Mins = B_On_Time_M then
Blue_Day_Cycle = DAWN
b_cnt = 0
endif
end select

'*** Do WHITE daily cycle
select case White_Day_Cycle
case DAWN
lcdout $FE,$94+11,"WT: DAWN "
if w_cnt = w_Fadein_time and W_PWM < w_max then
W_PWM = W_PWM + 1
w_cnt = 0
endif
if W_PWM = W_max then White_Day_Cycle = DAY
case DAY
lcdout $FE,$94+11,"WT: DAY "
if RTC_Hours = W_Off_Time_H and RTC_Mins = W_Off_Time_M then
White_Day_Cycle = DUSK
w_cnt = 0
endif
CASE DUSK
lcdout $FE,$94+11,"WT: DUSK "
if w_cnt >= w_Fadeout_time and W_PWM > w_min then
W_PWM = W_PWM - 1
w_cnt = 0
endif
if W_PWM = W_min then White_Day_Cycle = NIGHT
case NIGHT
lcdout $FE,$94+11,"WT: NIGHT"
if RTC_Hours = W_On_Time_H and RTC_Mins = W_On_Time_M then
White_Day_Cycle = DAWN
w_cnt = 0
endif
end select

hpwm 1,W_PWM,1500
hpwm 2,B_PWM,1500


gosub Read_Clock


i = (((RTC_Secs>>4)&$0F)*10)+(RTC_Secs&$0F)
lcdout $FE,$80,"BLUES ",dec3 (B_PWM *100)/255,"%"
lcdout $FE,$C0,"WHITES ",dec3 (W_PWM *100)/255,"%"

gosub USB_Plugged

if TX_READY = 1 and plugged = 1 then gosub SendUSB
if RX_READY = 1 and plugged = 1 then gosub GetUSB
if plugged = 0 then FirstSend = 1 'If we unplug then reset the first read packet as dont want it!
lcdout $FE,$D4+6," ",dec RX_READY
'**** FINSISH BUTTON CODE ****
if PBUTTON = 1 then
LCDOUT $FE,1
goto mainmenu
endif
goto main


'************************************************* ***************
' LCD Backlight time
' Keeps the LCD backlight on until time is met unless its set to
' always on.
'************************************************* ***************
LCD_Blight:
if LCD_Mode = 0 then '10 seconds
LCD_Timer = 10
elseif LCD_Mode = 1 then '30 seconds
LCD_Timer = 30
else
LCD_Timer = 60 '1 minute
endif
LCD_Time = LCD_Time + 1
if LCD_Time = 100 then
LCD_Tmr = LCD_Tmr + 1
LCD_Time = 0
endif
if LCD_Tmr >= LCD_Timer then
low LCD_BACKLIGHT
LCD_Tmr = 0
LCD_Time = 0
endif
return

'************************************************* ***************
' USB Services.
' Send and recieve data packets
'
' Packet sizes are 64 bytes which should cover the amount of
' data we need for now.
'************************************************* ***************
SendUSB:
for i = 0 to USBBufferCount - 1
read i,USBTXBuffer[i] 'Read the eeprom data and store in the outward bound buffer
next i
SendData:
USBOut 1, USBTXBuffer, USBBufferCount , SendDATA ' if bus available, transmit data
return

GetUSB:
USBin 1, USBRXBuffer, USBBufferCount, Timeout ' if bus available, receive data
if Firstsend = 0 then
for i = 0 to USBBufferCount - 1
write i,USBRXBuffer[i] 'Write the eeprom data received from the PC
next i
gosub Read_eeprom 'Read eeprom data into the variables
else
Firstsend = 0
endif
Timeout:
return

' If USB plugged display USB on the display
USB_Plugged:
if plugged = 0 then
lcdout $FE,$91," "
else
lcdout $FE,$91,"USB"
endif
return

'************************************************* *****************
' LED Fade calculations
' This routine takes the fade in/out durations and also the min/max
' LED power values and calculates what the duration is between
' changing the PWM value to give us a smooth fade from min to max
Calc_Fade:
vb_1 = ((b_fade_in.highbyte * 60) + b_fade_in.lowbyte) *60 'Get total duration time in seconds
vb_2 = b_max - b_min 'Work out the 'distance' the lights go from min to max
b_fadein_time = vb_1 / vb_2 'Get number of seconds between each PWM change
vb_4 = vb_1 // vb_2 'Get fractions of a second
if vb_4 >=5 then b_fadein_time = b_fadein_time + 1 'If its over half a second then round up

vb_1 = ((b_fade_out.highbyte * 60) + b_fade_out.lowbyte) *60
b_fadeout_time = vb_1 / vb_2
vb_4 = vb_1 // vb_2 'Get fractions of a second
if vb_4 >=5 then b_fadeout_time = b_fadeout_time + 1 'If its over half a second then round up

vb_1 = ((w_fade_in.highbyte * 60) + w_fade_in.lowbyte) *60
vb_2 = w_max - w_min
w_fadein_time = vb_1 / vb_2
vb_4 = vb_1 // vb_2 'Get fractions of a second
if vb_4 >=5 then w_fadein_time = w_fadein_time + 1 'If its over half a second then round up

vb_1 = ((w_fade_out.highbyte * 60) + w_fade_out.lowbyte) *60
w_fadeout_time = vb_1 / vb_2
vb_4 = vb_1 // vb_2 'Get fractions of a second
if vb_4 >=5 then w_fadeout_time = w_fadeout_time + 1 'If its over half a second then round up
return

'Lets say 2 hours (120 mins) & 191 for the fade amount (ie 0 to 255 or 0% to 100% intensity)
'So we need to do:
' convert hours into minutes, then add minutes and then multiply by 60 to convert to seconds
' so: 2 hours = 120 mins + 0 mins * 60 to get 7200 seconds
' The distance is now based on the converted % into the PWM range of 0-255
' calculate the 'distance' the light goes from min to max (0 to 255 in this eg: 75% = 191 so: 191- 0 = 191)
' now divide total seconds by 'distance' ie: 7200 / 191 = 37.69 seconds between each PWM change
' Now we test the milliseconds and if above .5 we round up to the next second


'************************************************* *****************
' Check current time and adjust the position in the cycle to
' make sure that its where it should be in case of a power failure
' or if the settings are changed via the PC
Check_Lighting:
if rtc_hours < b_on_time_h then 'Are we earlier than the fade in time?
blue_day_cycle = NIGHT 'Yes so set the current mode to night
white_day_cycle = NIGHT
elseif rtc_hours > b_off_time_h then 'Are we later than time off?
vb_1 = b_off_time_h + b_fade_out.highbyte 'need to find out if were actually past the end of the fade out time
vb_2 = b_off_time_m + b_fade_out.lowbyte
if vb_2 > 59 then 'if the minutes are more than 59
vb_1 = vb_1 + 1 'then add 1 to the hour
vb_2 = vb_2 - 60 'Adjust the minutes back to between 0-59
endif
if rtc_hours > vb_1 and rtc_mins > vb_2 then
blue_day_cycle = NIGHT 'Yes so set the current mode to NIGHT
white_day_cycle = NIGHT
else
blue_day_cycle = DUSK 'No, were inbetween so set to DUSK
white_day_cycle = DUSK

vb_1 = rtc_hours - b_off_time_h 'Calculate the time difference between on time and current time
vb_2 = rtc_mins - b_off_time_m
vb_3 = (vb_1 * 3600) + (vb_2 * 60) 'Convert all to seconds
B_PWM = B_max - (vb_3 / b_fadeout_time) 'Divide by the seconds count between each PWM to get how far we are in

vb_1 = rtc_hours - w_off_time_h 'Calculate the time difference between on time and current time
vb_2 = rtc_mins - w_off_time_m
vb_3 = (vb_1 * 3600) + (vb_2 * 60) 'Convert all to seconds
W_PWM = w_max - (vb_3 / w_fadeout_time) 'Divide by the seconds count between each PWM to get how far we are in
endif
else
vb_1 = w_on_time_h + w_fade_in.highbyte 'need to find out if were actually past the end of the fade out time
vb_2 = w_on_time_m + w_fade_in.lowbyte
if vb_2 > 59 then 'if the minutes are more than 59
vb_1 = vb_1 + 1 'then add 1 to the hour
vb_2 = vb_2 - 60 'Adjust the minutes back to between 0-59
endif
if rtc_hours > vb_1 and rtc_mins > vb_2 then
blue_day_cycle = DAY 'Yes so set the current mode to DAY
white_day_cycle = DAY
B_PWM = B_MAX
W_PWM = w_max
else
blue_day_cycle = DAWN 'No, were inbetween so set to DAWN
white_day_cycle = DAWN

vb_1 = rtc_hours - b_on_time_h 'Calculate the time difference between on time and current time
vb_2 = rtc_mins - b_on_time_m
vb_3 = (vb_1 * 3600) + (vb_2 * 60) 'Convert all to seconds
B_PWM = b_min + (vb_3 / b_fadein_time) 'Divide by the seconds count between each PWM to get how far we are in

vb_1 = rtc_hours - w_on_time_h 'Calculate the time difference between on time and current time
vb_2 = rtc_mins - w_on_time_m
vb_3 = (vb_1 * 3600) + (vb_2 * 60) 'Convert all to seconds
W_PWM = w_min + (vb_3 / w_fadein_time) 'Divide by the seconds count between each PWM to get how far we are in
endif
endif
return
'************************************************* *****************
' Read Eeprom data into variables
Read_eeprom:
read 0,w_on_time_h 'Whites ON time hours
read 1,w_on_time_m 'Whites ON time minutes
read 2,w_off_time_h 'Whites OFF time hours
read 3,w_off_time_m 'Whites OFF time minutes
read 4,w_fade_in.highbyte 'Whites fade IN duration hours
read 5,w_fade_in.lowbyte 'Whites fade IN duration minutes
read 6,w_fade_out.highbyte 'Whites fade IN duration hours
read 7,w_fade_out.lowbyte 'Whites fade IN duration minutes
read 8,w_min 'Whites MIN intensity
read 9,w_max 'Whites MAX intensity
read 10,b_on_time_h 'Whites ON time hours
read 11,b_on_time_m 'Whites ON time minutes
read 12,b_off_time_h 'Whites OFF time hours
read 13,b_off_time_m 'Whites OFF time minutes
read 14,b_fade_in.highbyte 'Whites fade IN duration hours
read 15,b_fade_in.lowbyte 'Whites fade IN duration minutes
read 16,b_fade_out.highbyte 'Whites fade IN duration hours
read 17,b_fade_out.lowbyte 'Whites fade IN duration minutes
read 18,b_min 'Whites MIN intensity
read 19,b_max 'Whites MAX intensity

W_Min = (W_Min *255)/100 'Convert intensity % to real PWM value (from 0-100% to 0-255)
W_Max = (W_Max *255)/100
B_Min = (B_Min *255)/100
B_Max = (B_Max *255)/100
gosub Read_Clock
gosub Check_Lighting
return


'************************************************* *****************
Read_Clock:

I2CRead SDA_pin,SCL_pin,$D0,$00,[RTC_Secs,RTC_Mins,RTC_Hours,RTC_WDay,RTC_Day,RTC_M onth,RTC_Year,RTC_Ctrl]
If RTC_Hours.6=1 then
CounterA=(RTC_Hours>>4)&$01 ' Work-Out 12 or 24 hour Display for Hours
else
CounterA=(RTC_Hours>>4)&$03
endif
CounterA=CounterA*10+(RTC_Hours&$0F) ' Display Hours appropriately for 12 or 24 hour Mode
If RTC_Hours.6=1 then

LCDOut $FE,$D4,#CounterA
else
LCDOut $FE,$D4,#CounterA Dig 1,#CounterA Dig 0
endif

LCDOut ":",#(RTC_Mins>>4)&$0F,#RTC_Mins&$0F

i = (((RTC_Hours>>4)&$0F)*10)+(RTC_Hours&$0F)
rtc_hours = i
i = (((RTC_Mins>>4)&$0F)*10)+(RTC_Mins&$0F)
rtc_mins = i


Return


'************************************


MyTimer:
Tick_Tmr = Tick_Tmr + 1
if Tick_Tmr >107 then
Tick_Tmr = 0
b_cnt = b_cnt + 1
W_cnt = W_cnt + 1
endif
@ INT_RETURN

mainmenu:

LCDOUT $FE,$80,"Setup Menu"
lcdout $FE, $C0, "Select Option"

IF Option = 1 THEN lcdout $FE, $D4, "Set Time and Date "
if option = 2 then lcdout $FE, $D4, "op2 "
if option = 3 then lcdout $FE, $D4, "op3 "
if option = 4 then lcdout $FE, $D4, "opt4"
if option = 5 then lcdout $FE, $D4, "Run "
IF PBUTTON THEN Option = option + 1

if option >5 then option = 1
Pause 250
If option = 1 Then
If S_butt = 0 Then
LCDOUT $FE,1
'Gosub SetButtonRelease
'goto setup
endif
endif


If option = 2 Then
If S_butt = 0 Then
LCDOUT $FE,1
'Gosub SetButtonRelease
'goto opt2
endif
endif


If option = 3 Then
If S_butt = 0 Then
LCDOUT $FE,1
'Gosub SetButtonRelease
'goto opt3
endif
endif

If option = 4 Then
If S_butt = 0 Then
LCDOUT $FE,1
'Gosub SetButtonRelease
'goto opt4
endif
endif

If option = 5 Then
If S_butt = 0 Then
LCDOUT $FE,1
'Gosub SetButtonRelease
goto main
endif
endif


Goto mainmenu

Darrel Taylor
- 18th February 2013, 19:43
Malcolm,

I'm running your program here on a LAB-XUSB.
I had to change some things to make it run on it. And I made a program for the PC to just send/receive some data over USB.

Your program is sending out 127 reports per second when the USB is plugged in.
I'm not sure if your friends PC app can handle that many reports while updating GUI sliders etc..
It also fills up the USB buffer before the PC app connects, so when it does connect, it gets hit hard with a whole bunch of reports.

When I send data to it via USB, it saves the data to EEPROM and continues sending the new data at 127 reports per second.

So the USB portion is working properly.
You just need to limit the data going out.
It should really only send the data by request from the PC, instead of all the time.

This was all quite evident after adding the USB status LED's from post #3.

Scampy
- 18th February 2013, 20:22
Darrel,

thanks for taking the time out to test the code and report your findings.

I assume that ideally the PC program should send a request to the PIC, which then responds and sends the report, rather than the PIC constantly sending out reports when connected ?

I'll drop the guy a mail to see if he can come up with a revised application.

Your contribution is very much appreciated

Malcolm

Charlie
- 19th February 2013, 09:46
A simple interim step might be sending only 1 report per second or even less. There'll be lots of work to get a query/response protocol going and a simple slow down might meet your needs for this one-off project, or at least let you work other areas of the code while you're waiting for PC side changes.

Scampy
- 19th February 2013, 10:19
Hi Charlie,

Yes I have other parts of the code to develop, and whilst it would be a nice function to have, I can live without it if I must.

To prove it wasn't a duff chip or hardware issue with the USB port on the EasyPic5 board I downloaded the USB Demo example (Mr E's) and stuck a 4mhz resonator in the board - it ran fine and I could toggle the LEDS on portB from the PC application. I then swapped the resonator for a 20 mhz xtal and set the fuses in the programmer accordingly and tested again - it ran sweetly. So the issue is with the code, and I have no reason to doubt DT's explanation.

Thanks for the comments

Malcolm

Scampy
- 19th February 2013, 23:43
@Darrel,

Hi, need some advice regarding the way the HID260 USB routine works.

I commented out the send section in my main code thus:


; if TX_READY = 1 and plugged = 1 then gosub SendUSB
if RX_READY = 1 and plugged = 1 then gosub GetUSB
if plugged = 0 then FirstSend = 1 'If we unplug then reset the first read packet as dont want it!


So this way I can check the sending of data from the PC to PIC. As the software is written to read the EEPROM data from the PIC first, the application displayed garbage values in the sliders which was as expected. Opening up the port monitor I got one TX report for each time I clicked on the update button, and whilst I couldn't see what values I was sending to the PIC, the LCD appeared to respond and display the change of values.

I removed the comment from that line and again the PIC was spewing report after report as you found. I therefore added the line



SendData:

USBOut 1, USBTXBuffer, USBBufferCount , SendData ' if bus available, transmit data
plugged = 0
return


The theory being that once it's sent that first report the software would then behave as if the USB lead had been removed - there was no change when the USB port was monitored. So I tried the following



USBOut 1, USBTXBuffer, USBBufferCount , SendData ' if bus available, transmit data
TX_READY = 0
return


Again, my logic thinking that once the report had been sent and the TX_ready state set to "not ready" it would stop transmission - but again no change. It's as if something else is over-riding the values used, which originate in the included HID260 file. The code I'm using doesn't have any other calls or conditions connected with the USB, just those IF / THEN statements to check the status of ready and plugged, and then the send and receive routines. Can you advise where or why over-riding these variables have no effects.

Cheers

Malcolm

Darrel Taylor
- 20th February 2013, 02:27
PLUGGED, RX_READY and TX_READY are status bits that DT_HID copies from the hardware USB registers on each USB interrupt.

They allow your program to know the USB status.
But they do not control anything.

Why not just increment a variable, and only send data when it reaches 127.
Then it should send it once a second.

Scampy
- 20th February 2013, 10:18
Thanks for the info,

I've added a counter and condition as suggested and it does indeed now pole once a second, but I'm still getting the same issue, but this time it's easy to spot. I can move a slider, click update, but a second later it will revert back to it's default setting. Watching the port monitor, only RX reports are being shown. However if I comment out the part of the code which does the checks for TX ready and plugged, I can send updates from the PC, which is shown in the port monitor window. It's as if the RX part on the PIC side is being ignored

Darrel Taylor
- 20th February 2013, 14:52
I'm guessing that you still haven't enabled the status LED's from post #3.
Since you're using an EasyPIC board, you should have lots of LED's to use.
It makes it a lot easier to see what's going on.

The PIC program has no problem receiving data from my PC app.
Can you post your friend's PC app?

Scampy
- 20th February 2013, 19:24
Hi Darrel,

Sorry, no I've not had much chance of hooking up the LEDs to the USB activity... Looking at the manual for the EasyPIC5, setting the jumpers to route the D+ and D- etc from the socket to RC4 and RC5 results in these pins being disconnected from the rest of the board. I'll see if a breadboard approach might help.

I've attached a zip file containing the PC software, hope that it helps

Darrel Taylor
- 20th February 2013, 20:02
The Status LED's do not connect to the D+ or D- pins.
You can use any pin besides those.

And your problem is definately in the PC program you just posted.

It does not update anything until it receives a report from the PIC.
Even the clock in the bottom right corner only updates on each report from the PIC.

If you make it so the PIC does not send anything, then the PC program will send updates.
But as soon as the PIC sends something, the PC program will never send anything again.

That program needs some serious work.

Scampy
- 20th February 2013, 20:49
Darrel,

As stated, I didn't write the bulk of the code, as both it and the application was written by a friend, who said that back in 2006 it worked fine but on a different chip. I can confirm that he did indeed write the application to function in that way, ie the PIC sends data when it detects the USB connected and then sends updated data back once the update setting button is pressed. I agree a better approach would of been to have the application set the values and then simply update the PIC once the update button has been pressed. I could ask him if he still has the source code and if it can be modified to work that way.

Thanks again for your input.