View previous topic :: View next topic |
Author |
Message |
hamid9543
Joined: 31 Jan 2013 Posts: 63
|
Complete the task of slave[SOLVED] |
Posted: Fri Jan 04, 2019 6:06 am |
|
|
So I have a device set as the I2C master, and the rest of the devices on the bus are set as slaves. The master sends a command to each slave, and the slave executes this task (running motors, PID stuff, important time-sensitive code). I would like to be able to know when the slave is finished executing its task. The only way I can see to do this is to constantly have the master poll the slave, but this creates an issue, because every time the master polls the slave, it triggers an i2c interrupt on the slave and quits running the motor code for a short amount of time.
Is there anyway to solve this?
Last edited by hamid9543 on Mon Feb 10, 2020 1:22 pm; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Fri Jan 04, 2019 7:43 am |
|
|
Using just the I2c, no.
However you could have a single line back to the main chip, and either
have all the slaves 'wire ored' ro this, so that it is pulled high by a resistor,
with the slaves pulling it low when they are busy, or have the slaves
each pulse it low when they complete a task, so the master can then
poll for who this was. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Fri Jan 04, 2019 1:06 pm |
|
|
As Mr. T says, using I2C no...
Can you use RS-485 or some other form of PIC2PIC communications ? If you can use the HW UARTs within PICs then interrupts are easy to do!
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Fri Jan 04, 2019 1:33 pm |
|
|
The UART has the advantage of being bi-directional, so messages can
be sent back.
However with the extra lines to control a trasceiver (which would be
needed for a multiple shared bus), again extra pins would be needed. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Fri Jan 04, 2019 2:53 pm |
|
|
Yeah, forgot about the RS-485 needing 'direction control' pin. I'm kinda 'stuck' on a true single wire system designed 3 decades ago that allows address,outgoing data, incoming data to be sent on a single wire (plus ground), bidirectionally over miles of copper. Sigh. That was 1/2 my lifetime ago, no wonder I can't keep up with 'new' stuff !
Course now that PICs are less than a buck, an extra I/O pin shouldn't cut into the profit margin
Jay |
|
|
hamid9543
Joined: 31 Jan 2013 Posts: 63
|
|
Posted: Sat Jan 05, 2019 9:18 am |
|
|
Ttelmah wrote: | Using just the I2c, no.
However you could have a single line back to the main chip, and either
have all the slaves 'wire ored' ro this, so that it is pulled high by a resistor,
with the slaves pulling it low when they are busy, or have the slaves
each pulse it low when they complete a task, so the master can then
poll for who this was. |
what i understand is you mean when slave complete its task pin become low and when slave is doing task the pin has remained in high level.
and during this master checks slave pin status |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Sat Jan 05, 2019 9:38 am |
|
|
yes....
and IF that I/O line is an Interrupt input, the Master doesn't have to 'poll' or 'scan' l or look at it.
The 'slave' devices would trigger the interrupt and your ISR would then tell 'main', someone has finished their task. 'main' would have to decide who it was.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Sat Jan 05, 2019 11:54 am |
|
|
Or as I said you could 'wire or', by only driving low, when the chips
are busy. Then when the line goes high all the devices have finished.
You could also go 'sneaky' with the pulse mode.
If you use a CCP to detect this, you could time the pulse width.
Then have the slaves each send different width pulses, and you would
know which one has signalled.
Obviously the slaves would have to test that the line was high before
transmitting. |
|
|
hamid9543
Joined: 31 Jan 2013 Posts: 63
|
|
Posted: Fri Jan 18, 2019 7:59 am |
|
|
pin_A0 of 18f66k80 has been connected to pin_A0 16f1829 and this pin send the end of task to master
master code
Code: | #include <18f66k80.h>
#fuses INTRC_IO //Internal RC Osc, no CLKOUT
#fuses NOPROTECT //Code not protected from reading
#fuses NOWDT //No Watch Dog Timer
#fuses NOPUT //No Power Up Timer
#fuses NOMCLR //Master Clear pin used for I/O
#fuses NOCPD //No EE protection
#fuses BROWNOUT
//#use delay(internal=16MHz)
#use delay(clock=64MHz,crystal=16MHz)
#use rs232(UART1, RECEIVE_BUFFER = 4, baud = 38400)
#use i2c(MASTER,i2c1,slow,FORCE_HW)
void main()
{
int8 ldr;
while(TRUE)
{
if(input(PIN_A0)==1) printf("No Ready\n\r");
if(input(PIN_A0)==0){
printf("started i2c\n\r");
i2c_start();
i2c_write(0x29);
char lsb = i2c_read(0);
i2c_stop();
printf("stopped i2c\n\r");
}
}
} |
and slave
Code: | #include <16f1829.h>
#fuses INTRC_IO //Internal RC Osc, no CLKOUT
#fuses NOPROTECT //Code not protected from reading
#fuses NOWDT //No Watch Dog Timer
#fuses NOPUT //No Power Up Timer
#fuses NOMCLR //Master Clear pin used for I/O
#fuses NOCPD //No EE protection
#fuses BROWNOUT
#device ADC=8
#use delay(internal=32mhz)
#use i2c(SLAVE,sda=PIN_B4,scl=PIN_B6,address=0x28,slow,FORCE_HW)
#use rs232(RECEIVE_BUFFER = 4,baud = 9600,UART1)
#define LDR_NUM 6
#define R_PIN PIN_A5
int8 command=0;
int8 adc_channel[LDR_NUM]={4,5,6,9,8,7},ldrc[LDR_NUM];
#INT_SSP
void ssp_interrupt()
{
int state = i2c_isr_state();
if(state < 0x80) // Master is sending data
{
command=i2c_read();
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_write(data[state-0x80]);
printf("*\n");
}
output_high(pin_a0);
}
void main()
{
setup_adc_ports(sAN4|sAN5|sAN6|sAN7|sAN8|sAN9);
setup_adc(ADC_CLOCK_DIV_8);
enable_interrupts(global);
enable_interrupts(INT_SSP);
output_low(pin_a0);
while(true)
{
if(input(pin_a0)){
for(int8 d=0;d<LDR_NUM;d++)
{
set_adc_channel(adc_channel[d]);
delay_us(10);
ldr[d]=read_adc();
printf("1\n");
}
printf("\r");
for(i=0;i<LDR_NUM;i++)
{
if(ldr[i] >100) data_ldr[i]=1;
else data_ldr[i]=0;
printf("2\n");
}
printf("\r");
output_low(pin_a0);
printf("3\n\r");
}
} } |
master print "no ready"
slave print nothing |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Fri Jan 18, 2019 10:50 am |
|
|
The slave I2C, will have hung.
You can't have things that cause delays in an I2C receive routine.
Your slave routine is driving A0 high, whenever any character is received
on the I2C, not at the end of the task.
SLOW is not correct syntax for the slave (no speed for a slave, the master
controls the timing).
You are both testing, and driving the pin in the slave. You can only do this if
you use an 'open collector' drive. Otherwise the reading of the input will
set the pin to float, and it'll no longer be driven. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Fri Jan 18, 2019 4:30 pm |
|
|
He really should have lines..like 'old school' RS-232 hand shaking was....
hmm..wonder if that's even taught in school today ?
Jay |
|
|
hamid9543
Joined: 31 Jan 2013 Posts: 63
|
|
Posted: Sat Jan 19, 2019 8:15 am |
|
|
temtronic wrote: | He really should have lines..like 'old school' RS-232 hand shaking was....
hmm..wonder if that's even taught in school today ?
Jay |
would you please give me your suggestion?
what can i use instead of RS-232?
is there better alternative? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Sun Jan 20, 2019 2:04 am |
|
|
For a multi slave system with proper bidirectional communication
(but half duplex so only one direction at a time), look at RS485.
Just three wires needed at each PIC. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
Re: Complete the task of slave |
Posted: Sun Jan 20, 2019 6:25 am |
|
|
hamid9543 wrote: |
I would like to be able to know when the slave is finished executing its task. The only way I can see to do this is to constantly have the master poll the slave, but this creates an issue, because every time the master polls the slave, it triggers an i2c interrupt on the slave and quits running the motor code for a short amount of time.
Is there anyway to solve this?
|
Suppose you have 3 i2c slave chips. Each slave could have an output
i/o pin that sends out a logic '1' when it's doing the task, and a logic '0'
when it's doing nothing (or has finished the task).
Then create a 4th i2c slave chip. Connect the status indicator pins from
the first 3 slaves to pins B0, B1, and B2 on the 4th slave. Then poll the
4th slave to read that port and send it back to you.
Also, Microchip sells i2c slave chips that are i/o expanders. This would do
it easily, though they require some setup commands to be sent initially. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Sun Jan 20, 2019 7:05 am |
|
|
Do you HAVE to use I2C ? As pointed out it's not the best for 'communications'. To get the feedback of 'task done', you need more pins, more interconnections.
RS-485 only needs 2,so actually saves I/O line in the 'comm bus'. It's been used for 'device 2 device communications for decades.T he alarm industry adopted it a long time go. CCS in their FAQ section shows how to use a single wire to have several PICS talk to each other. I've used a variation of that for 3 decades.
I2C is generally only good for very short distances (on same PCB).
Without knowing the details of the project, perhaps you can use one powerful PIC instead of several smaller ones ? Give us more details and we may have other options for you.
Jay |
|
|
|