Man I'm sorry to hear the Pi is tearing up cards. I don't understand why it would be doing that. All I can think is that it is shutting down and dropping power before the Raspbian OS is finished halting.
You can adjust the time the PIC will wait before pulling power with this function:
Code: Select all
I would suggest putting this in the setup() function of the Arduino processor so it sends it to the PIC each time it starts up.
Here is the note about this function:
Code: Select all
Set shutdown delay (in milliseconds) PIC will wait when doing
a shutdown sequence. This is the time to allow Pi to safely
shutdown before being powered off. Suggest not to change default,
but you may want to make it longer if your Pi is running a
lot of processes that need time to terminate. Max delay 20 seconds.
sdIntervals is count of 20ms cycles BTN_PWR must be held before
a shutdown sequence is initiated.
Default sdDelay = 5000, Default sdIntervals = 40
I have never heard of the Pi destroying cards just by running the IO lines. I haven't had a card go bad yet but maybe I've been lucky. Unfortunately that would be an issue with the Pi that I can't control. I was let down by the Pi overall. I didn't realize there were so many issues with the hardware pins on that board until we were well into the project. The hardware bug in the I2C port of that chip on the Pi has been a real challenge to work around.
Here is an option I want to consider for getting more reliable comms between the Pi and the PIC. It's a bit of work, but if anyone was willing to spend some time on it, it's not especially hard, and will likely solve all the problems some people are still having with the I2C communication erroring.
Normally the Pi talks straight to the PIC via I2C, and the Arduino also can talk to the PIC via I2C. The comms between the Arduino and the PIC seem to be solid and reliable, it's only when we introduce the Pi talking on that bus that we tend to have problems.
The idea is to send the commands from the Pi through the Arduino. The Pi talks to the Arduino over SPI, which seems to work fine - that is how the demo code is controlling the motors. Servo movement commands (from the Pi) go straight to the PIC via I2C, but the motor commands go to the Arduino via SPI, and that part seems to work really well.
We can pipe the commands to the Arduino via SPI, then the Arduino can send them to the PIC via I2C.
Here is how one would go about doing this:
1) Study the python code on the Pi that controls the motors. It packs up a SPI packet and sends it. This packet is 10 bytes long, plus a checksum byte. That is already in place. It packs up the value "130" as the first byte, which is the key to the Arduino to interpret the packet as motor control. I propose we use a different value, say 140 or something, that would tell the Arduino to relay the data via I2C. We could then make a packet on the Pi that would be 140 at the start, then the rest of the data would be the target I2C register and the arguments that go with it.
2) On the Arduino, on the Pi Slave sketch, we can expand the existing SPI handler (it's toward the bottom of the Comms tab), the function is named "SPI_Handler", and add a new case statement for the new value. Then add a routine to grab the data in the packet and sent it via I2C, which you can see how to do by looking at the other functions in the Comms tab.
3) The above works fine for sending, but getting a query back will be a bit more complex. Maybe you use a different first value like 141 or something if the command needs a reply. I this case, the Pi needs to send a first command, then it needs to wait long enough for the query to take place, then it can run another packet and during the exchange of that second packet, it will receive data back from the Arduino (SPI sends 1 bye out and at the same time receives 1 byte back). On the Arduino side, if it is a query (like a sensor value), the Arduino can run the normal function to do the query, then take the response and pack it up into the SPI_BufferOut array. When the Pi comes back and does the second step, this SPI_BufferOut will be transferred back to the Pi on the next SPI exchange. The Pi can then grab the results from this SPI response.
That really shouldn't take long either. SPI is much faster than I2C, so the two SPI transfers will be fairly fast, you'll just need to wait long enough for the I2C transaction to happen between the Arduino and PIC. I think 1 to 2 milliseconds should be enough for this, but you may need some trial and error here.
It's rare you'd need to poll a sensor faster than this, so it would probably work for most things.
Let me know if any questions on that and I will try to help anyone through it.