Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 15:38 06 Jul 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : How to drive 13 relays.

     Page 1 of 2    
Author Message
Paul_L
Guru

Joined: 03/03/2016
Location: United States
Posts: 769
Posted: 10:11pm 25 Dec 2016
Copy link to clipboard 
Print this post

I hope that everyone here had an enjoyable Christmas!

I need to drive 13 relays at a distance of about 20 feet. The relays are on the 8 relay boards commonly available from China, complete with optocouplers and driver circuits. Each board has 8 input pins which could be driven directly by 8 uM digital output pins plus pins for a separate 5v or 12v power supply and ground. I am running out of output pins on the uM E100 board.

The required interface speed is very slow. All 13 relays only need to be updated about twice every second.

I would like to try to send a serial bit stream to two daisy chained shift registers with latching outputs on a support board about 20 feet from the E100 uM board and let the shift registers outputs control the relay board inputs. I suppose either the TPIC6B595 or the 74HC495B would be applicable.

My first problem is that I am not sure if the SPI functions will work. SPI was intended for short distance communication. At a distance of 20 feet I believe the bit stream might get scrambled. So, will SPI work over a 20 foot distance and how slow should the SPI clock speed be set?

My second problem is that I am not sure what the best substitute for the SPI protocol would be. I could program a separate 44 pin uM to read s string from a serial buffer and then extract individual characters from the string using MID$() and use them to set each of 13 individual output pins. But, I don't really want to use a programmed uM in an inaccessible location where it would be inconvenient to load or modify the program. So, should I switch to using uni-directional buffered serial sent blind with no acknowledgement or handshaking to a second uM 44 pin chip running an MMbasic program?

My third problem is that I can't see an easy way to set individual bits in a 13 bit (or 16 bit) word (like &B 0000 0000 0000 0000) in response to the state of 13 individual MMbasic Boolean variables. I don't believe that MMbasic provides any way to set or clear an individual bit in a string variable (probably 2 characters long). If I pre-define an array to contain every possible combination and select one there will be 2^13 choices or 8192. Similarly I don't believe there is any MMbasic procedure which will evaluate or expand a string like "0101010101010101" into a binary number like &B0101010101010101. So, how do I get those 13 individual Boolean variables into the bit string?

Paul in NYEdited by Paul_L 2016-12-27
 
Zonker

Guru

Joined: 18/08/2012
Location: United States
Posts: 767
Posted: 02:56am 26 Dec 2016
Copy link to clipboard 
Print this post

Humm...

I think I would like the "Remote MM' approach.. That way you could set it up with a simple ASCII type protocol, possibly using Rs-485, and use it for input and output port IO.. If needed, you could also set it up with a known startup pattern of on and off settings for the relay outputs...
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3282
Posted: 05:48am 26 Dec 2016
Copy link to clipboard 
Print this post

  Paul_L said  I can't see an easy way to set individual bits in a 13 bit (or 16 bit) word

For example, to set bit six:
nbr% = nbr% OR (1<<6)

Geoff Graham - http://geoffg.net
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 07:31am 26 Dec 2016
Copy link to clipboard 
Print this post

There is no direct way to manipulate a character in a string.
You could use a left$ and right$ to get the parts left and right of the 'bit' that you want to change and then add them together again.

I remember Visual Basic had a MID statement which could replace characters in a string by giving the location and optional length. Might be a nice addition to consider.


Microblocks. Build with logic.
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2429
Posted: 09:58am 26 Dec 2016
Copy link to clipboard 
Print this post

pascal/delphi uses square bracketed references to access individual characters. translating into mmbasic-talk:

a$[5] is the 5th character in a$
a$[0] is the length of a$
a$[7] = chr$(65) would change the 7th character of a$ into an "A"

print a$[7] would be equivalent to print mid$(a$,7), while a$[7] = chr$(65) would be equivalent to a$ = left$(a$,6)+chr$(65)+mid$(a$,8)

another approach would be to allow assignments to len(a$) and mid$(a$, n) to change length and any single character respectively.

geoff: how easy would either approach be to implement? and how palatable as an extension to the language?


cheers,
rob :-)
 
Paul_L
Guru

Joined: 03/03/2016
Location: United States
Posts: 769
Posted: 02:47pm 26 Dec 2016
Copy link to clipboard 
Print this post

@Geoff - Thanks, but I don't understand your example of bitwise manipulation.

Where old.nbr%=&B0000 0000 0000 0000

1 << 6 means you shift &B0000 0000 0000 0001 left six places to become
&B0000 0000 0100 0000

Then you OR (bitwise multiplication) it with old.nbr%

1<<6 = &B0000 0000 0100 0000
old.nbr% = &B0000 0000 0000 0000
new.nbr% = &B0000 0000 0000 0000

You made no change in old.nbr%.

And where old.nbr%=&B0000 0000 0100 0000

When you OR 1<<6 with old.nbr%

1<<6 = &B0000 0000 0100 0000
oldnbr% = &B0000 0000 0100 0000
newnbr% = &B0000 0000 0100 0000

Again, you made no change in old.nbr%.

I must be dense but I don't get it.

Paul_L
Edited by Paul_L 2016-12-28
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9589
Posted: 02:58pm 26 Dec 2016
Copy link to clipboard 
Print this post

You're not dense.
Bit manipulation confuses the hell out of me too.
I'll be interested in the replies to this - maybe I can learn something too.
Smoke makes things work. When the smoke gets out, it stops!
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6269
Posted: 03:19pm 26 Dec 2016
Copy link to clipboard 
Print this post


Paul, are you testing this with recent version of MMBasic.
V4.5 or earlier doesn't have integers so the precision required for 16 bits is not there.
  Quote   a% = &B0000000000000000
b% =
1 << 6

c% = a%
OR b%
d% = a%
AND b%

PRINT "a% = ";BIN$(a%,16)
PRINT "b% = ";BIN$(b%,16)
PRINT "c% = ";BIN$(c%,16)
PRINT "d% = ";BIN$(d%,16)



  Quote  > RUN
a% = 0000000000000000
b% = 0000000001000000
c% = 0000000001000000
d% = 0000000000000000
>



The above was run on a V5.2 micromite (my MMEdit test server which you can access from the comfort of your couch while watching the cricket.

Jim
VK7JH
MMedit
 
bigmik

Guru

Joined: 20/06/2011
Location: Australia
Posts: 2949
Posted: 03:28pm 26 Dec 2016
Copy link to clipboard 
Print this post

Hi Paul,

As most would know, I am not really any good at software coding but I would approach this along this line..

Set your relays as you need them (0=off or 1=on)

Rly1=1
Rly2=0
Rly3=0
.
.
.
.
Rly13=1

Then call a subroutine (I would use GOSUB but the programmers would probably use a function or SUB.

GOSUB Set_Rlys:

Set_Rlys:
New_Byte=(Rly13 * 8192)+(Rly12 * 4096)+(Rly11 * 2048) ........... + (Rly2 * 2) + Rly1
RETURN


If the total exceeds the max line length then split into 2 or 3 lines

Kind Regards, (and apologies if not a good method)

Mick
Mick's uMite Stuff can be found >>> HERE (Kindly hosted by Dontronics) <<<
 
Paul_L
Guru

Joined: 03/03/2016
Location: United States
Posts: 769
Posted: 04:05pm 26 Dec 2016
Copy link to clipboard 
Print this post

@Zonker -

I like the idea of using a second MM as well, I could pass it this string

A$="nnnYnnnY...Y-"

indicating that relays 4, 8 and 12 were to be pulled in. I could then test A$ with MID$()to find the "Y"s.

BUT .... the second MM will be inaccessible stuck up between joists in the basement. If it malfunctions somehow and requires re-programming it will be a real pain. It would be lovely if I could somehow remotely modify or re-load its program but I don't know how that could be done.

Any suggestions.

@MicroBlocks -- @robert.rozee --

I don't regard the lack of a MID statement or pascal/delphi's square brackets as being terribly inconvenient because we can easily build a transmission string to control 13 pumps from an array like this:

buildTRstring: 'receives boolean globals p1 through p13, sets global tr$
LOCAL A$(13) LENGTH 1
' the variables, set elsewhere, which control the pumps are now set
if p1 then A$(1)="Y"
' set each A$(2..12) here
if p13 then A$(13)="Y"
tr$="": for i=1 to 13 : tr$=tr$+A$(i) : next
endsub 'buildTRstring

decodeTRstring: 'receives global tr$, operates pumps
LOCAL pins(13)=nn,nn,nn,nn,nn,nn,nn,nn,nn,nn,nn,nn,nn ' output pins to pump relays
for i=1 to 13
if tr$(i)="Y" then
PIN(pins(i))=1
else
PIN(pins(i))=0
endif
next
endsub 'decodeTRstring

Have you got any suggestions about easy ways to re-program the remote uM?

Paul in NY
 
Paul_L
Guru

Joined: 03/03/2016
Location: United States
Posts: 769
Posted: 04:35pm 26 Dec 2016
Copy link to clipboard 
Print this post

Jim, you're right, I'm wrong. I'm doing bitwise boolean in my head. I don't have a uM here. I got it backwards.

A bitwise AND multiplies the bits together like this
0000000000000000 AND
0000000001000000 gives
0000000000000000

A bitwise OR does a logical inclusive OR on each pair of bits so that the result is 0 if both bits are 0 otherwise the result is 1 like this

0000000000000000 OR
0000000001000000 gives
0000000001000000

I think I've got it. I think I've got it. This might make it possible to use the shift register approach instead of a remote uM with the attendant programming difficulties. Thanks!

What about my other reservations about communicating with the shift register. At a distance of 20 feet I believe that an SPI bit stream might get scrambled. Will SPI work over a 20 foot distance if I set the SPI clock speed very low? Or can I send a buffered serial stream blind with no acknowledgement or handshaking to the shift register and somehow clock the shift register?

How do I access your test server from the comfort of my couch? It would be great to be able to test these things myself.

Just when you got me straightened out you had to bring up cricket again, didn't you. Now I can't decide whether to sign off as Paul or Pavel Artur Jan Waclaw Lepkowski. I don't want anyone to confuse me with the other Paul, so I'll just say ....

Paul in NY
Edited by Paul_L 2016-12-28
 
Zonker

Guru

Joined: 18/08/2012
Location: United States
Posts: 767
Posted: 04:51pm 26 Dec 2016
Copy link to clipboard 
Print this post

Hep Paul...

I don't think a remote MM, even if it's hard to get at is that big of a deal... The simplest way is to just string a USB cable to it and leave it "hang down" so you could get to it if needed... You could "get fancy" and add either a Blue-tooth or WiFi adapter to the console port and get access through the radio... You could then transmit out current status updates... You could also add a relay feedback circuit that checks if the relay is following your commands... If it becomes defective, (open coil, stuck contacts, ect..) the MM would report the defect back to the controller...

Just some thoughts and head scratchin...
 
VK2MCT
Senior Member

Joined: 30/03/2012
Location: Australia
Posts: 120
Posted: 06:21pm 26 Dec 2016
Copy link to clipboard 
Print this post

I like the idea of a remote MM (Micromite has enough control pins)
Suggest using RS232. (via buffers maybe)
I'd go for 4 bits of a word being for which relay and another bit for on/off.
I would send each command thrice. The remote MM needs to get the same 3 consecutive words before activating a relay. (noise immunity)
You will also need to consider pullups/downs so that startup is elegant.

How much current for control do the relay boards need?

John B
VK2MCT
 
Paul_L
Guru

Joined: 03/03/2016
Location: United States
Posts: 769
Posted: 08:14pm 26 Dec 2016
Copy link to clipboard 
Print this post

Hi John B

If I do decide to use a remote uM I would probably just send a character string and forget about bit manipulation. Repeating each command sounds like a good idea.

The relay boards are the cheap ones with the integrated opto-couplers and driver circuits so the input current is minimal.

Paul in NY
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2429
Posted: 09:55pm 26 Dec 2016
Copy link to clipboard 
Print this post

you could just connect up to the console, leaving the remote micromite sitting at the command prompt, and send text commands of the form:
PIN(n) = value

no programming at the remote end is required, and even an MX150 would do the job just fine.


cheers,
rob :-)
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3282
Posted: 11:28pm 26 Dec 2016
Copy link to clipboard 
Print this post

There are some MMBasic bit manipulation functions here: http://fruitoftheshed.com/MMBasic.Bit-Manipulation-Functions.ashx

EDIT: I have just noticed that the parameters and functions in that library entry should be declared integers, as follows:

FUNCTION BitSet(value AS INTEGER, bit AS INTEGER) AS INTEGER
BitSet=value OR (2^bit)
END FUNCTION


FUNCTION BitRes(value AS INTEGER, bit AS INTEGER) AS INTEGER
BitRes=(value OR (2^bit)) XOR (2^bit)
END FUNCTION


FUNCTION BitTest(value AS INTEGER, bit AS INTEGER) AS INTEGER
BitTest=SGN(value AND (2^bit))
END FUNCTION

GeoffEdited by Geoffg 2016-12-28
Geoff Graham - http://geoffg.net
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2170
Posted: 03:20am 27 Dec 2016
Copy link to clipboard 
Print this post

  Geoffg said  
EDIT: I have just noticed that the parameters and functions in that library entry should be declared integers, as follows:
Geoff


corrected - cheers
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 04:57am 27 Dec 2016
Copy link to clipboard 
Print this post

You could also use an array to hold the on/off state of a relay.
Changing any relay can be done by using its index in de array.
If you want to have them combined in a single string you can then append each value from the array to that string.


Microblocks. Build with logic.
 
VK2MCT
Senior Member

Joined: 30/03/2012
Location: Australia
Posts: 120
Posted: 11:17am 27 Dec 2016
Copy link to clipboard 
Print this post

The 74HC495B option would require 3 wires plus power to the remote.
The 3 wires can be easily programmed, manipulating MM pins 'manually' rather than SPI.

John B
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6269
Posted: 04:32pm 27 Dec 2016
Copy link to clipboard 
Print this post

Paul,
6 meters (I use metric to confuse you) is short for RS232.
I use MAX2323 modules at each end to give better noise immunity than TTL.
If you use the console port on the 'remote' micromite, you can easily get to the 'local' end and switch it from the master micromite to a USB adapter and program it without having to pull the house apart.
You just have to be careful that your program doesn't send a ctrl-C while running.

Jim

VK7JH
MMedit
 
     Page 1 of 2    
Print this page
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025