Maker Pro
Maker Pro

Wireless trigger for LEDs and buzzers

foTONICS

Sep 30, 2011
332
Joined
Sep 30, 2011
Messages
332
This thread encompasses two projects for me. This flashing LED project started by cyberteen (who I haven't seen post on this thread in quite some time) and another side project of mine where I want to keep electronic score at a basketball game.

The reason for sleeping the micro is b/c each net will have it's own transmitter operating a sensor which will most likely be run on batteries so power saving is probably an issue
 

foTONICS

Sep 30, 2011
332
Joined
Sep 30, 2011
Messages
332
Bit-banged SPI is pretty straightforward but I'm not familiar with the functions provided in your library, whatever it is. In the unlikely event that you have problems, I'm sure that I, or someone else here, can help.

MPLAB X IDE using Xc8

Also I don't think I will need full duplex operation of the NRF24L01's, I figure each net will only transmit, holding the value of the score on it's own micro. The micro controlling the seven segment LED's will just act as a receiver.

Now that I think about it, would it make sense to make all of them transceivers so that I can remotely reset each net's goal count?
 

KrisBlueNZ

Sadly passed away in 2015
Nov 28, 2011
8,393
Joined
Nov 28, 2011
Messages
8,393
If you have a situation where multiple slaves have information that needs to be communicated upstream, and you need that information to be received reliably, you should have some kind of poll-response system where the upstream device periodically polls downstream devices, or at least expects them to transmit on a regular basis. Otherwise the upstream device won't know whether a slave device is even present or not. The slave may know that it can't get a message upstream (assuming messages are acknowledged in each direction) but if it's unattended, it can't tell anyone that there's a problem.

You should have a good think about how best to arrange communication. Try to consider future requirements as well as current ones, and consider how best to handle loss of communication upstream, downstream, and in both directions.

I used to work for a SCADA (telemetry) company so I have some experience here. If you describe your setup and what information needs to be transferred and when, I can give you some suggestions.
 

foTONICS

Sep 30, 2011
332
Joined
Sep 30, 2011
Messages
332
I like your suggestion about how the upstream device needs to be able to tell if something is wrong with a downstream device trying to send data.

I also assume upstream would be the master and downstream would be the slave.

So this is what I think so far of my setup:

1. Each net has it's own transceiver (slave) that regularly sends a "hey I'm still alive" type of message

2. The transceiver controlling the LED's (master) would expect a status update every 50ms or so. I also don't want to cause any sort of noticeable delay should someone score on one goal while the other one is sending a status update (I'm referring to the master updating the LED display)

3. I haven't decided whether the sensor that detects a goal will trip an interrupt or the micro will just continually poll the sensor and look for an event. I'm thinking I'll do the poll option b/c I don't want the interrupt of a goal to interfere with the master/slave checkup

4. I have thought about incorporating a WDT so that micro's up on the net can reset themselves should they run into trouble but I don't want them to loose the current goal count (if they need to reset in the middle of a game). I could probably do something where all the slave does is send a command to increment the goal and not have the actual total count for goals on it. that way if it resets it doesn't need to be reloaded with the current count

Any thoughts?
 

KrisBlueNZ

Sadly passed away in 2015
Nov 28, 2011
8,393
Joined
Nov 28, 2011
Messages
8,393
What do you mean by "net"? Do you mean a physical net that's strung around the goal hoop?

How many slaves will be present?

Do the slaves all communicate with a single transceiver at the master?

What happens if two slaves try to send messages at the same time? Will the master receive both separately? Just one? Or will they clobber each other so the master receives neither?

So you want to make a system to display scores at a basketball game. These scores will be displayed by a single master. It will get its information from a number of slave units, which will probably be battery powered. Each slave will be connected to a sensor that detects some event in the game, and it needs to notify the master of this information. Right so far?

If I understand your requirements, my suggestion would be:

The master should poll the slaves in a loop, at a rate that allows all slaves to be polled within a time that ensures a reasonably short delay from a goal being scored (the ball going into the net) until the score display updated; I expect 100~200 ms would be fine.

When the master transmits a poll message, the addressed slave responds with a message containing a number (an 8-bit number would be enough) that increments whenever a goal is detected and wraps around to zero when it overflows. The master keeps a record of the last known number from each slave and when a new number is received, it calculates the difference, updates the score, and updates the last known number for that slave. This means that if message(s) are missed, when communication is re-established the numbers will update correctly, unless the slave or master has reset; that might have to be handled specially.

Messages must include a slave address. Messages should include some kind of error detection. Parity and checksums are not strong, but might be good enough. CRCs (cyclic redundancy check) are recommended; an 8-bit CRC would be fine for short messages. If the check is wrong, the message is ignored.

If the microcontroller in the slave draws a significant amount of power in comparison to the transceiver's idle current, it can be put into power-down mode in between polls. If the microcontroller's current consumption is not significant, there's no point doing that.

If the master doesn't receive a response from an addressed slave for a certain amount of time, it may need to raise some kind of alarm to tell someone that there's a problem.

I would suggest using a single message format, with fixed length, in both directions. The message would contain framing characters, slave address, flags, values (free-running counter value) and checksum/CRC.

If you want to use a watchdog in the slaves, or the master for that matter, you will need to think about what happens when context is lost. You will probably also want the slave to notify the master that it has reset, so you can investigate the reason. If you use the incrementing 8-bit free-running counter that I suggested above, you could reserve a specific value, for example 0xFF, to mean "uninitialised"; when the master receives that value, it would set its last known count for that slave to zero, and its next poll to that slave could include a flag that tells the slave to reset its counter to 0. I haven't thought that one through and there could be pathological conditions where it would fail. But have a think about these ideas.

Edit: Can you post a link to a PDF data sheet for the transceiver module?
 
Last edited:

foTONICS

Sep 30, 2011
332
Joined
Sep 30, 2011
Messages
332
What do you mean by "net"? Do you mean a physical net that's strung around the goal hoop?

Yes the typical rope net found on basketball goals, this also means I have to investigate which kinds of sensors would be best

Do the slaves all communicate with a single transceiver at the master?

Yes, the transceiver at the master is the one taking in the information from the two basketball goals (each goal having it's own NRF25L01) and processing it if necessary. It's also the master that updates/controls the 7-segment LED's

Edit: In earlier posts I say "LED's but I mean 7-segment LED's


What happens if two slaves try to send messages at the same time? Will the master receive both separately? Just one? Or will they clobber each other so the master receives neither?

If I remember the datasheet correctly there are multiple channels to play with. I'll get back to you on that once I double check

So you want to make a system to display scores at a basketball game. These scores will be displayed by a single master. It will get its information from a number of slave units, which will probably be battery powered. Each slave will be connected to a sensor that detects some event in the game, and it needs to notify the master of this information. Right so far?

Correct, the master will also do the math behind keeping score. All I want the slaves to do is say "hey a goal was scored, increment team A's count" and the master will update the current count

When the master transmits a poll message, the addressed slave responds with a message containing a number (an 8-bit number would be enough) that increments whenever a goal is detected and wraps around to zero when it overflows. The master keeps a record of the last known number from each slave and when a new number is received, it calculates the difference, updates the score, and updates the last known number for that slave. This means that if message(s) are missed, when communication is re-established the numbers will update correctly, unless the slave or master has reset; that might have to be handled specially.

The only reason I didn't want to have the slave keeping track of the actual count was in case it got reset for any reason, but you bring up valid points. Maybe some sort of dual redundancy in both slave and master. Like what if a slave reset because the watch dog timed out and the first line in it's code is to ask for the count from the master?

If the master doesn't receive a response from an addressed slave for a certain amount of time, it may need to raise some kind of alarm to tell someone that there's a problem.

I'm sure I have some old speakers laying around that I could use to produce an irritating enough sound from

Edit: Can you post a link to a PDF data sheet for the transceiver module?

here ya go
 

KrisBlueNZ

Sadly passed away in 2015
Nov 28, 2011
8,393
Joined
Nov 28, 2011
Messages
8,393
I wasn't suggesting that each slave keep a count of goals per se; just a counter that increments on each goal and wraps around in a defined way. It doesn't even need to be an 8-bit counter. The reason is so that if communication is lost for a time, when it is re-established, if multiple increments occurred during the downtime, they are not lost.

If you have a flag that the slave sets only once in one message response, then if the master doesn't receive that message due to a temporary comms problem, the increment is lost. To avoid that problem, you would need some kind of acknowledgement flag from the master, so the slave knows that the set flag was detected by the master. This gets messy; using two free-running counters is a bit tidier.

Yes, I was thinking about the slave asking for the count from the master after it resets. If the master sends its counter value in each poll, the slave can use that value to initialise its own count if it has just reset (or just started up normally).
 

foTONICS

Sep 30, 2011
332
Joined
Sep 30, 2011
Messages
332
I understand serial communication but I have never actually designed something that uses it before (outside of flip flops and the like). That being said I need to do some catch up reading on the PIC's datasheet before I can move ahead with any of this.

I'll keep the thread posted as I make headway
 

foTONICS

Sep 30, 2011
332
Joined
Sep 30, 2011
Messages
332
bit banging is just setting up a for-loop and adding in some while-loops to look for the start and stop bits right? Aside from staggering the sampling so you take in values in the middle of the data is there anything else I should consider?

Are interrupts necessary?

Since this is asynchronous I should do some sort of ACK?
 

KrisBlueNZ

Sadly passed away in 2015
Nov 28, 2011
8,393
Joined
Nov 28, 2011
Messages
8,393
Are you talking about asynchronous serial communication with slave units or SPI communication with LED drivers?

SPI doesn't use start and stop bits. You have a clock signal, which is generated by the master (your MCU), and a data signal from the master to the slave (sometimes called MOSI, master output / slave input).

You normally need some kind of framing signal to provide context for the data; for a 74HC595 shift register (which can drive eight LEDs) this is a "latch clock" signal that transfers the most recently received data bits into the output latch. For a dedicated LED driver IC, this would be some kind of chip select signal.

You can also have a feedback signal (MISO, master input / slave output) that can be used to check that the serial data has been fed around the loop correctly, but in an LED driving application, it's common to just update the display continuously, so any disturbance will only be fleeting.

Interrupts aren't necessary for SPI. Some MCUs have a built-in SPI peripheral, which is quicker and easier to use than bit-banging. Bit-banging is easy enough if the device doesn't have an SPI peripheral.

SPI is synchronous.

If you're talking about the message transfers between the scoring devices and the master device, I suggest defining a single, simple message format that is used in both directions, and a using simple poll-response protocol where the master polls the scoring devices alternately using one message and expects another message in response.
 

foTONICS

Sep 30, 2011
332
Joined
Sep 30, 2011
Messages
332
Are you talking about asynchronous serial communication with slave units or SPI communication with LED drivers?

I thought serial communication and SPI were the same things (sorta)

You say serial is asynchronous and SPI is synchronous, which would be better in my application? I would rather not have to add any drivers for the LED so I was thinking asynchronous.

So if I don't use SPI but rather asynchronous serial communication do I even need to figure out bit banging? is that what the USART on my PIC16F627A is for?

I apologize for any seemingly oblivious questions, serial data is a gray area for me


Edit: I just saw on the datasheet that USART is for +/-15V NRZ format and that I would have to run it through a level converter which I won't be doing
 
Last edited:

foTONICS

Sep 30, 2011
332
Joined
Sep 30, 2011
Messages
332
Okay I just looked more at the wireless transceivers datasheet and it uses MOSI/MISO SCK and the like so I believe it's expecting synchronized data
 

KrisBlueNZ

Sadly passed away in 2015
Nov 28, 2011
8,393
Joined
Nov 28, 2011
Messages
8,393
SPI is serial (that's what the "s" stands for, after all), but it is synchronous - there is an explicit clock signal (SCK). Generally, "serial data" (like the data used with a serial port, with start and stop bits) is asynchronous; a single data signal, with character framing (the start and stop bits).

But you're right, the interface with the NRF24L01 is SPI only. Even the transmitted and received data is transferred via SPI. So there is no asynchronous serial data in your project. Sorry for confusing you unnecessarily.

If your PIC doesn't have an SPI peripheral built-in, you will have to use bit-banging for the SPI communication with the NRF24L01.

You would also have to use bit-banging for the SPI communication with the LED driver, if you use one, and I think you may need one. It depends how many LEDs you have in your display.

Bit-banging SPI is not difficult at all. Just a few functions to write. Just Google those search terms.
 

foTONICS

Sep 30, 2011
332
Joined
Sep 30, 2011
Messages
332
What would be a nice way to test if my PIC is transmitting serial data correctly? I don't have a scope at home but I may be able to use one at work
 

BobK

Jan 5, 2010
7,682
Joined
Jan 5, 2010
Messages
7,682
Do you have a PICKIT 2? It has a 4-bit logic analyzer feature that you could use for that.

Bob
 

foTONICS

Sep 30, 2011
332
Joined
Sep 30, 2011
Messages
332
Hey everyone just a little update:

I've haven't been working on this for a while due to time constraints but I'm starting back at it now. I've gotten the hang of bit banging and have even selected the sensor I'm going to use here.

I like this one because of the analog output. I'm not sure if the basketball goal I'm going to be attaching this to has a net or not. I hope that doesn't interfere with the sensor too much
 

foTONICS

Sep 30, 2011
332
Joined
Sep 30, 2011
Messages
332
Just figured maybe you guys would be interested in where I am at so far. Keep in mind that this is full of holes and missing information, so pretty much just a framework of what I basically want it to do.

Note also that for now I'm not going to worry about whether or not the receiver and transmitter can communicate with each other yet. going to focus first on getting SPI up and running then I'll worry about redundancy








/*DEVELOPER NOTES
*
* I need one program for the master (controlling the 7seg display) and one program
* for the slave (monitors the sensor on the basketball net)
*
* need to select a sensor, something with analog output will make it easier
*
* I need a clock pin and a argument where data is only shifted when this pulse is high
*
* find out how long it takes for a clock signal to stabalize a high value
*
* create a loop to shift out 8 bits
*
* this syntax shifts bits:
* sPORTA.port = sPORTA.port << 1;
*
* datasheet says a mismatch condition will continue to trigger the interrupt,
* so once the ISR is started the first thing I need to do is write a zero to RB5.
* the rest of portb needs to be outputs, this will stop them from being used as interrupt
* pins
*
* do I want to use another piece of hardware for the 7 seg display or do I want
* to write it in software? I might have this chip 74ls48?
*
*
*do i really need a clk pin if I'm just toggling one of the pins. most likely
*i will be toggling either RA7 or RA0 depending on if the NRF takes MSB or LSB
*first, respectively
*
* keeps writing a value until it senses information from the transceiver, use
* interrupt, then update value, returns to main program using new value
*
*on the NRF the CSN needs to be kept high to start with, then brought low when
* you want to give it a SPI command.
*
* I need to configure the NRF24L01 first, think i need w_register
*
* i need a lookup table to analyze data faster the decimal number 2,
* or binary 0010, is not the same as what I would write to the 7 seg display
*
* dont forget about ISR, see commented code at bottom to remember how to set up
* use porta to write to the 7 seg display, use the pins on portb that don't mess
* with the portb interrupt as the data and clock
*/
//--------------------------------------------------------------------------------------------------------
//THIS PROGRAM IS FOR THE PIC CONTROLLING THE 7 SEG DISPLAY
//for now not needed since only receiving data, doesn't care if transmitter
//hiccups
#include <pic16f627a.h>
//--------------------------------------------------------------------------------------------------------

//Configure device
#pragma config WDTE = OFF // Watchdog disabled
#pragma config PWRTE = OFF // Power-up Timer disabled
#pragma config MCLRE = OFF // Master-clear internally tied to VDD
#pragma config BOREN = OFF // Brown-out Detect disabled
#pragma config CPD = OFF // Data memory code protection off
#pragma config CP = OFF // Code protection off
//--------------------------------------------------------------------------------------------------------
//variables
unsigned int clk=0; //variable that will be used to clock in/out data. do I even need this variable?
unsigned int static score=0; //variable that keeps score. USE PORTA to read data, then write to this variable
unsigned int static backup_score=0;//just in case variable, used if either the
//transmitter or receiver fails/loses data. may have to be stored on external
//hardware (SD CARD?)
volatile union //union because I want each input/output of PORTA to be accessible while also allowing the writing/reading of
//the entire port
{
int port;
struct
{
unsigned RA0 : 1;//reserves one bit and labels it as "RA0"
unsigned RA1 : 1;//reserves one bit and labels it as "RA1"
unsigned RA2 : 1;//reserves one bit and labels it as "RA2"
unsigned RA3 : 1;//reserves one bit and labels it as "RA3"
unsigned RA4 : 1;//reserves one bit and labels it as "RA4"
unsigned RA5 : 1;//reserves one bit and labels it as "RA5"
unsigned RA6 : 1;//reserves one bit and labels it as "RA6"
unsigned RA7 : 1;//reserves one bit and labels it as "RA7"
};
}sPORTA;

//--------------------------------------------------------------------------------------------------------

//function prototypes
int init_pic(void);//configures the PIC for operation
int NRF_setup(void);//configures the NRF(wireless transceiver)

//--------------------------------------------------------------------------------------------------------
main(void)//main program
{

init_pic();//calls pic setup function
NRF_setup();//calls NRF setup function

while (1)//will continually run until ISR executes
{
//I need to load the data into a variable
//then take LSB first
//raise the clock pin high to shift the bit into the NRF
//bring the clock pin low
//shift data
//repeat
//keep updating display, waiting for interrupt which signals
//change in score
}
}
//--------------------------------------------------------------------------------------------------------
int init_pic(void)
{
OPTION_REGbits.T0CS=0;//internal instruction clock
OPTION_REGbits.PSA=1; //prescaler assigned to WDT so timer0 increments at a 1:1 ratio
INTCON=0x88;//sets bit 7(global interrupts) and bit 3(RB port interrupt on change bit) high
CMCON=0x07;//turns comparators off
TRISA=0;//set PORTA to outputs
TRISB=0x80;//set RB7 as input(interrupt on change) and rest as outputs (pulled low with external resistors)
PORTA=0;//clear PORTA prior to operation
PORTB=0;//clear PORTB prior to operation
}
//--------------------------------------------------------------------------------------------------------
int NRF_setup()
{

}
//--------------------------------------------------------------------------------------------------------
//interrupt service routine
void interrupt isr(void)
{
//service RB7 ISR
PORTB=0x00;//can't write to the entire port since it will share the bit bang SPI to the NRF
INTCONbits.RBIF=0; //clear interrupt flag, might not need this, writing to the portb will clear the flag




}
//--------------------------------------------------------------------------------------------------------
 

foTONICS

Sep 30, 2011
332
Joined
Sep 30, 2011
Messages
332
Hey guys,

I've done a little clean up of my code and I think I'm really close to getting a link up and running. Since I'm mediocre at coding I may have made a mistake when it came to passing the address of a variable to a function that assigned that address to a pointer. Here is what I have so far:

//This part is just me making comments to remind myself of how I'm going to hook up the actual circuit

// THIS CODE IS INTENDED FOR USE WITH A NRF24L01 USED AS A PRIMARY RECEIVER
#include <pic16f627a.h>
#include <xc.h>//this header is needed for delay macro
#define _XTAL_FREQ 4000000//this value is needed for the delay macro

//RB0=7seg_output
//RB1=7seg_output
//RB2=7seg_output
//RB3=7seg_output
//RB4=7seg_output
//RB5=7seg_output
//RB6=7seg_output
//RB7=IRQ - - this pin is active low when triggered by interrupt.
//RA0=CE
//RA1=CSN
//RA2=SCK
//RA3=MOSI
//don't use RA4-pull down
//RA5=MISO*
//RA6=so far N/A-pull down
//RA7=so far N/A-pull down
//--------------------------------------------------------------------------------------------------------


//THIS IS WHERE I CONFIGURE THE PIC16F627A's INTERNAL REGISTERS

//Configure device
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has PGM function, low-voltage programming enabled)
#pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//--------------------------------------------------------------------------------------------------------
//internal NRF registers
int NRF_Config[8]={0,1,0,0,1,1,1,1};//forces data that is received to trigger the IRQ pin
int NRF_EN_AA[8]={0,0,0,0,0,0,0,0};
int NRF_EN_RXADDR[8]={0,0,0,0,0,0,0,1};//enable datapipe zero only (for now)
int NRF_RF_CH[8]={0,0,0,0,0,0,1,0};//set up RF channel as 2.402GHz (2.4GHz+2MHz)
int NRF_RF_Setup[8]={0,0,0,0,1,1,1,1};
//------------------------------------------------------------------------------
int PICin[8]={0,0,0,0,0,0,0,0};//used as buffer for data leaving NRF
int NRFin[8]={0,0,0,0,0,0,0,0};//used as buffer for data entering NRF
//--------------------------------------------------------------------------------------------------------

//The function prototype below named "int shiftout(int *)" is the only thing I really don't know if I coded right. The program compiles but I don't know if it will actually work yet. //My idea is have arrays of 1's and 0's. I will then send the address of the first element in the array to this function. This function will then take this address and assign it to a //temporary pointer (at the bottom of my code you will find the function itself). Will it work like this?

//function prototypes
int init_PIC(void);//configures PIC for operation
int init_NRF(void);//configures NRF for operation
int shiftout(int *);//loop that shifts data into NRF
//int shiftin(void);//loop that shifts data into uController
//--------------------------------------------------------------------------------------------------------

//It's important to note that this program is not finished, inside the while statement I will be assigning values to PORTB which will operate a 7 segment LED. I also have to //code in the interrupt

main(void)//main program
{
init_PIC();
init_NRF();

while(1)
{

}
}
//--------------------------------------------------------------------------------------------------------
int init_PIC(void)
{
OPTION_REGbits.T0CS=0;//internal instruction clock
OPTION_REGbits.PSA=0; //prescaler assigned to WDT so timer0 increments at a 1:1 ratio
INTCON=0x00;//sets bit 7(global interrupts) and bit 3(RB port interrupt on change bit) high
CMCON=0x07;//turns comparators off
PORTA=0x00;//clear PORTA prior to operation
PORTB=0x00;//clear PORTB prior to operation
TRISA=0x20;//0010 0000
TRISB=0x80;//set RB7 as input(interrupt on change) and rest as outputs
PORTAbits.RA1=1;//set CSN high
}

int init_NRF(void)
{
PORTAbits.RA1=0;//set CSN low, this alerts NRF that it's about to receive SPI data
__delay_us(500);//delay to make sure enough time elapses between CSN going low and NRF ready for data packet
//--------------------------------------------------------
//update buffer,shift in w_register instruction,shift in NRF config settings
//NRF_Config
NRFin[2]=1;
shiftout(&NRFin[0]);
shiftout(&NRF_Config[0]);
//--------------------------------------------------------
//update buffer,shift in w_register instruction,shift in nrf_en_aa settings
//NRF_EN_AA
//the below for loop is only used to set all the elements of the NRFin array to 0
for(int a=0;a<8;a++)
NRFin[a]=0;
NRFin[2]=1;
NRFin[7]=1;
shiftout(&NRFin[0]);
shiftout(&NRF_EN_AA[0]);
//--------------------------------------------------------
//update buffer, shift in w_register instruction, shift in nrf_en_rxaddr settings
//EN_RXADDR
for(int a=0;a<8;a++)
NRFin[a]=0;
NRFin[2]=1;
NRFin[6]=1;
shiftout(&NRFin[0]);
shiftout(&NRF_EN_RXADDR[0]);
//update buffer, shift in w_register instruction, shift in nrf_rf_ch settings
//NRF_RF_CH
for(int a=0;a<8;a++)
NRFin[a]=0;
NRFin[7]=1;
NRFin[4]=1;
shiftout(&NRFin[0]);
shiftout(&NRF_RF_CH[0]);
//update buffer, shift in w_register instruction, shift in nrf_setup settings
//NRF_RF_Setup
for(int a=0;a<8;a++)
NRFin[a]=0;
NRFin[4]=1;
NRFin[6]=1;
shiftout(&NRF_RF_Setup[0]);
}

//*buff is a temporary pointer that will be assigned the address to the first element in whatever array is passed to it, currently the only thing I'm not 100% about
int shiftout (int *buff)
{
for (int b=0; b<8; b++)
{
PORTAbits.RA2=0;//bring CLK low
PORTAbits.RA3=*buff++;//put data on the MOSI pin
PORTAbits.RA2=1;//bring CLK high to shift in data to NRF
}
}
 

KrisBlueNZ

Sadly passed away in 2015
Nov 28, 2011
8,393
Joined
Nov 28, 2011
Messages
8,393
It looks like you're using an array of ints to hold the bit values to be sent to the NRF. That's very inefficient; an int is 16 bits wide, and you would only be using one bit of each int. If the NRF always expects eight bits at a time (which it looks like it does), you should construct the data in a single byte (uint8_t) variable, and transmit that one bit at a time with a function that takes one uint8_t as a parameter:
Code:
void shiftout(uint8_t bytevalue) {
    uint8_t bitn;
    for (bitn = 0; bitn < 7; ++bitn) {
        PORTAbits.RA2 = 0;                // Bring SPI clock low
        PORTAbits.RA3 = bytevalue & 0x01; // Extract bottom bit of bytevalue and assert it on MOSI
        PORTAbits.RA2 = 1;                // Bring SPI clock high - clock in the bit
        bytevalue >>= 1;                  // Shift bits downwards in bytevalue
        }//for bitn
    PORTAbits.RA2 = 0;                    // Bring SPI clock low (for tidiness only)
    }//shiftout
That function shifts eight bits out of bytevalue. The first time through the loop, it asserts the bottom bit (bit 0) on RA3 and clocks it into the NRF, then it shifts bytevalue right by one bit using the ">>= 1" operator, so bit 0 now contains the value that was in bit 1, and so on.
 
Top