Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

using a RTC in SF basic

MrDEB

Well-Known Member
I have a DS-1302 RTC module but how to use it?
I recall Jon Chandler made a vu meter clock but what he used for timing?
Am planning on a clock that has no hands, just LEDs but precision would be nice.
 
Does not seem to be the case @nigel– this edit was done about 10 hours after I posted my comment, and I'm pretty sure I've edited posts days after I made them when I notice a typo. See quote below with edited comment added.

Perhaps the updating period has been changed?, as far as I recall it used to be an hour or so?.

Good to know :D
 
Boards have been ordered, so now go onto the code, BUT!
Here is a short tibit I am trying to turn on individually 60 leds but putting it all in an array.
Instead of portc.0 = 1 would like to address led(x) = 1 then cycle through with a NEXT statement
Any thoughts on putting all in an array?


Code:
Device = 18F43K22
Clock = 16

// int osc and IO pin libraries
Include "intosc.bas"
#option DIGITALIO_INIT = true       // automatically call setalldigital
Include "setdigitalio.bas"

// lcd
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.2
#option LCD_EN = PORTD.3
Include "LCD.bas"
Include "convert.bas"
Dim led(60) As word
dim led(1) as portc.0
dim x as byte
// import LCD library...
//Include "LCD.bas"
//Include "utils.bas"

// program start...
trisc = %11111111
SetAllDigital
While true
Cls
WriteAt(1,1,"Hello World")
led(1) = 1
DelayMS(1500)
led(1) = 0
DelayMS(500)
Wend
 
Is there a limit to the number of CASE/SELECT statements? contemplating using 60 CASE SELECT
Code:
Device = 18F43K22
Clock = 16

// int osc and IO pin libraries
Include "intosc.bas"
#option DIGITALIO_INIT = true       // automatically call setalldigital
Include "setdigitalio.bas"

// lcd
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.2
#option LCD_EN = PORTD.3
Include "LCD.bas"
Include "convert.bas"
'Dim led(60) As word
Dim led1 As PORTC.0
Dim led2 As PORTC.1
Dim led3 As PORTC.2
Dim led4 As PORTC.3
Dim led5 As PORTC.4
Dim x As Byte
Dim MINUTE As Byte
// import LCD library...
//Include "LCD.bas"
//Include "utils.bas"

// program start...
x = 0
MINUTE = 0
TRISC = 0
PORTC = %00000000
SetAllDigital
While true
Cls
//led1 = 1
WriteAt(1,1,"Hello World")
WRITEAT(2,1,DECTOSTR(minute))


Select MINUTE


   CASE   = 1  led1 = 1

   CASE  = 5  led2 = 1  led1 = 0


endselect


x = minute + 1
MINUTE = MINUTE + 1
DelayMS(1000)
'led1 = 0
'DelayMS(500)
Wend
 
Using a test circuit
Code:
{
 dim Row_1 as portb.0  //rows are the minute led anodes  BLUE 3mm LEDS
 dim Row_2 as portb.1  //rows are the minute led anodes
 dim Row_3 as portb.2  //rows are the minute led anodes
 dim Row_4 as portb.3  //rows are the minute led anodes
 dim Row_5 as portc.2  //rows are the minute led anodes
 dim Row_6 as portd.4  //rows are the minute led anodes
 dim Row_7 as portd.5  //rows are the minute led anodes
 dim Row_8 as portd.6  //rows are the minute led anodes
 dim Row_9 as portb.4  //rows are the minute led anodes
 dim Row_10 as portb.5  //rows are the minute led anodes
 
 DIM COLUM-1 AS PORTA.0   // COLUMS ENABLE MOSFETS
 DIM COLUM-2 AS PORTA.1
 DIM COLUM-3 AS PORTA.2
 DIM COLUM-4 AS PORTA.3
 DIM COLUM-5 AS PORTA.4
 DIM COLUM-6 AS PORTA.5
 
 DIM G-1 AS PORTC.1     // THE GREEN 5mm LED ANODES   TO INDICATE HOURS
 DIM G-2 AS PORTC.2
 DIM G-3 AS PORTC.3
 DIM G-4 AS PORTD.0
 DIM G-5 AS PORTD.1
 DIM G-6 AS PORTD.2
 
 DIM GREEN-1 AS PORTE.0      // ENABLE GREEN LED MOSFETS
 DIM GREEN-2 AS PORTC.4
 
 DIM LEFT-EYE AS PORTC.5     // TO BLINK EVERY SECOND
 DIM RIGHT-EYE AS PORTC.6
 
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 //INPUTS FOR SETTING TIME
 
 DIM MINUTES AS PORTD.7
 DIM HOURS AS PORTE.1
 
 
 
Device = 18F43K22
Clock = 16

// int osc and IO pin libraries
Include "intosc.bas"
#option DIGITALIO_INIT = true       // automatically call setalldigital
Include "setdigitalio.bas"

// lcd
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.2
#option LCD_EN = PORTD.3
Include "LCD.bas"
Include "convert.bas"

{
   For One Second Update:

   8MHz Fosc = 2MHz internal clock = 0.5us per cycle (timer count)
   Use 16-bit Timer1, No Prescaler
   Set CCPR1 = 50000; Timer1 resets on match every 50000 counts = 25000us
   Each Timer1 reset requires 1 cycle compensation... so set CCPR1 = 49999
   40 interrupts x 25000us each = 1 second
}
Dim x As Byte
Dim LED0 As PORTC.0   //the red leds for testing
Dim LED1 As PORTC.1
Dim LED2 As PORTC.2
Dim LED3 As PORTC.3
Dim LED4 As PORTC.4
Dim LED5 As PORTC.5
Dim LED6 As PORTC.6
Dim LED7 As PORTC.7
//dim led(1) as portc.1
Dim C1 As Word Absolute $0FBE             ' CCPR1L + CCPR1H
Dim Int_Counter As Byte               
Dim update As Boolean
Dim secs,mins,hrs As Byte
Dim minute As Byte
Interrupt RTC()
   Dec(Int_Counter)
   If Int_Counter = 0 Then           
      Int_Counter = 40                    ' each interrupt = 25000us x 40 int's = 1 second
      update = true                       ' update LCD output
   End If
   PIR1.2 = 0                             ' clear CCP1 interrupt flag 
End Interrupt

Sub Clock24()
 Dim clk As String
    Inc(secs)
 
    If secs = 60 Then                     ' check each tally for rollover
       secs = 0
    
       Inc(mins)
//USE SELECT CASE TO INCREMENT THE MINUTE LEDS (60 - 3mm BLUE leds)     
  Select mins
   Case  = 1  LED1 = 1
   Case  = 2  LED1 = 0  LED2 = 1
   Case  = 3  LED2 = 0  LED3 = 1
   Case  = 4  LED3 = 0  LED4 = 1
   Case  = 5  LED4 = 1  LED5 = 1
   Case  = 6  LED5 = 0  LED6 = 1
// NEED TO ENABLE THE DIFFERENT MOSFETS AS NEEDED FOR HOURS (12 - 5mm green leds) and additional (3mm blue leds)

EndSelect
  If mins = 60 Then
          mins = 0   
          Inc(hrs)
  //ADD SELECT CASE FOR HOURS
          If hrs = 24 Then
             hrs = 0
          End If
       End If
    End If
    x = x + 1
    clk = DecToStr(hrs,2)                 ' output to LCD
    LCD.WriteAt(2,5,clk)
    clk = DecToStr(mins,2)
    LCD.WriteAt(2,8,clk)
    clk = DecToStr(secs,2)
    LCD.WriteAt(2,11,clk)
    update = false
End Sub

Sub Initialize()
   ADCON1 = 15
   secs = 0
   mins = 0
   hrs = 0
   Int_Counter = 40
   update = false
   LCD.Command(130)
   LCD.Write("24-HOUR CLOCK")
   LCD.Command(196)
   LCD.Write("00:00:00")     
   INTCON = 192                           ' enable GIE & PEIE
   T1CON = 0                              ' no prescaler timer OFF
   TMR1H = 0                              ' clear TMR1
   TMR1L = 0
   CCP1CON = 11                           ' enable special trigger event                   
   C1 = 49999                             ' set match value
   PIE1.2 = 1                             ' enable CCP1 interrupt
   PIR1.2 = 0                             ' clear CCP1 interrupt flag
   T1CON.0 = 1                            ' Timer1 ON
   Enable(RTC)                            ' enable jump to RTC ISR
End Sub

   Initialize
   //testing
x = 0
minute = 0
TRISC = 0
PORTC = %00000000
TRISC = 0
//
Output (LED0)
   While 1=1
      If update = true Then
         Clock24()                          ' update 24H Clock output
      End If
   Wend
board that has only 8 leds, this code appears to work
 
About Mid August, this thread inspired me ... My variation is a MQTT clock that is set by the internet. Not only can it function as a clock, if you have another MQTT device that for example measures resistance, volume (think circular VU bar graph meter) , the MQTT clock can be used as a meter. The video shows a test pattern for the MQTT clock.

In this design there are 10 identical PCB segments ... The one that determines "12 O'Clock" is the segment where you populate the ESP8266

Power can be applied from any segment

The center of the clock is hollow

Video Example (Test Pattern):
 

Attachments

  • CLOCK_v2_PCB.pdf
    58.5 KB · Views: 69
  • CLOCK_v2_SCH.pdf
    21.4 KB · Views: 64
Beautiful work! Good job!

Using shift registers in each segment does simplify things considerably. Great idea.

What's the overall diameter?
 
Nice. A 300mm clock for $5 worth of pcbs (assuming a Chinese fab). Nicely laid out, easy-to-assemble boards. Truly, I love it.

Are you connecting the boards with jumpers?

Would you mind posting a picture?
 
"Are you connecting the boards with jumpers?" - I am using standard pin headers and then pulling the plastic separator off.

Note: There is a slight error in the board which ends up being a compounding error. Notice the small gap on the left side of the image vs the right side. I used a credit card to get the spacing correct. It's off by about 0.8mm.
 

Attachments

  • 1727889489747.png
    1727889489747.png
    822.8 KB · Views: 59
  • 1727889929221.png
    1727889929221.png
    252.9 KB · Views: 62
"Are you connecting the boards with jumpers?" - I am using standard pin headers and then pulling the plastic separator off.

Note: There is a slight error in the board which ends up being a compounding error. Notice the small gap on the left side of the image vs the right side. I used a credit card to get the spacing correct. It's off by about 0.8mm.

Does that mean you had new boards made :D
 
"Does that mean you had new boards made" - No, but I had to re-work the connectors when I discovered the error. For a prototype, I'm ok with the GAP as long as it is even and symmetrical... If when I make a second batch I'll fix the PCB

Ideally, I would like to offer something like this as a kit, but I need to bring the price point down. Even sourcing components from LCSC and boards from Seeed , the shipping (about $60) is what is killing the price point.
 
I've had decent results shipping boards from JLC using "Global Express" (something like that). Takes a little longer, but it's reasonably quick.
 
I've had decent results shipping boards from JLC using "Global Express" (something like that). Takes a little longer, but it's reasonably quick.

I've just ordered some small boards, and they allow low cost slow shipping - but on larger boards low cost shipping isn't available - presumably it's a weight thing?.

5 small boards: $2.00
Shipping: $1.55
VAT: $0.71

Total: $4.26

Often my PCB orders (for work) have shipping over £100 (sudden switch from $ to £ :D )
 
That's a lot cheaper than the cheap rate to US.
 
MQTT - (Google is your friend) - Is a method to connect IoT devices to the internet through a broker or server using a simple publish and subscribe protocol over TCP/IP. In this case the "Clock" would be a client talking to the broker in the cloud. I have spun a server on a Digital Ocean account that contains a MQTT broker. Instead of using "Node Red", I have a python script that reads the system time and sends data to the broker which in turn the broker sends the data to the client "Clock". The Clock has no concept of time, it just displays what it receives over MQTT

 
I was thinking about the connections between boards and how to make it easier to assemble and perhaps a stronger mechanical connection....

If a dual-row header is positioned between the segments, with shorting jumpers between each pair of pins, you'd have a good mechanical connection that would be easier to assemble. My DRC doesn't squawk about being too close to the edge of the board. (Note - you'd lay the board out with a single row header in the proper position.)

I laid this out with the inner and outer arcs being 100mm apart. In this rotation, I see the inner arc needs a slightly larger radius to keep the board within a 100mm x 100mm rectangle.

I might consider laying out the board to accommodate either an ESP8266/ESP32 or a PIC18F micro + RTC. This provides the option of the MQTT/internet enabled solution or a dedicated clock. I struggle a bit with Arduino programming but I prefer Swordfish Basic on the PIC18F series. By provisioning for both gives options.


EasyEDA 10 segment.jpg
 
Noodling around with this a bit, for a clock application, 10 segments is inconvenient because the hour position on each segment is inconsistent.

A 6 segment version would allow keeping the hour locations consistent on each segment. Handy if you want to somehow identify hour locations on the silk screen.

It does complicate the shift register arrangement though.... more in a bit.

EasyEDA 6 segment clock.jpg
 
My take builds on the shift register approach (or perhaps detracts from it ;)); instead of using a single shift register and multiplexing, I've opted to use three shift registers without multiplexing. The 6 segment approach requires 20LEDs to have 2 rings, and the 4 extra bits from the multiplexer can drive 4 additional LEDs per segment.

Data only needs to be shifted out when the display requires updating. 18 bytes must be shifted when updating the display (i.e., all data must be shifted for an update of any LED). Shift registers are 24 cents at Digikey, so the extra cost is minimal.
 

Attachments

  • Schematic_clock-  10 segment, 300mm diameter_2024-10-04.png
    Schematic_clock- 10 segment, 300mm diameter_2024-10-04.png
    93 KB · Views: 52
Drat. The six segment version does not work – the large angle makes the chord of the angle the limiting feature rather than the radius for "cheap boards" (100mm × 100mm or less). This reduces the overall diameter to around 200mm instead of 300mm.
 

New Articles From Microcontroller Tips

Back
Top