Has anyone played with the Cypress wireless part?
Reference designs and photos over here:
http://www.cypress.com/portal/server.pt … wall=false
New part in the works puts a micro and the radio on one chip. No data sheets yet:
Has anyone played with the Cypress wireless part?
Reference designs and photos over here:
http://www.cypress.com/portal/server.pt … wall=false
New part in the works puts a micro and the radio on one chip. No data sheets yet:
John at J&S:
Has anyone played with the Cypress wireless part?
I have worked with both the Cypress wireless USB (which is not really
USB) and the nRF2401. In my opinion the nRF2401 is much easier to
use. There is much more to program with the Cypress and my luck
with range was not as good. Maximum data rate is not as good either.
With Cypress you have to do more in software. For example, the
nRF2401 will automatically error check using 8-bit or 16-bit CRC.
You have to do that in software with Cypress. I did not do a side
by side range comparison and it might not mean much anyway
unless you try different “gold” codes in the Cypress. I suspect
range is comparable at the same power level if everything is optimized.
The Cypress was just a lot more trouble to get going and the software
was much more involved. On top of the more complex programming
there were data sheet errors which made things worse. If you try
the Cypress, go with an evaluation kit so you have their reference
software to look at since it avoids some pitfalls due to data sheet
errors. I haven’t looked lately to see if the data sheets are fixed.
Atmel is a second source for Cypress with their own part number
and their data sheets were correct.
Bill: Thanks for the info.
The Cypress development kit is $750. I looked at the data sheet for the module, and it has ten I/O lines, and none of them says “Data In”. Argh.
I want to capture about 500msec of data from a three axis accelerometer. I need to sample about once per msec., so 3 channels x 8 bits x 1000 samples is 24kbps, not counting overhead?
Range is just a few feet. I’m using a cable right now, but it’s a little awkward.
Wow, I just checked the Nordic site, and they have a part with the radio and an MCU:
John at J&S:
I want to capture about 500msec of data from a three axis accelerometer. I need to sample about once per msec., so 3 channels x 8 bits x 1000 samples is 24kbps, not counting overhead?Wow, I just checked the Nordic site, and they have a part with the radio and an MCU:
The only problem with the Nordic chip which has an 8051 MCU is that
you still need an external serial EEPROM to load the program into the
MCU so it takes two chips. I prefer to use the nRF2401 and my choice
of MCU which has on-board flash program memory. This is still a
two-chip solution and I use my favorite MCU.
I have used the nRF2401 to transmit accelerometer data through
G forces up to 2000G with no problems.
Freescale (Motorola) has a small MC9S12C part. The 48 pin version is 7 mm square.
I don’t know C. The only programming I’ve done is HC11 assembly, so it shouldn’t be much trouble learning the HC12.
Bill: Do you think I could get away with just a transmitter at the sensor end? Any reason for the sensor to hear from the base station?
Nordic took the 2401 transmitter section and made it the 2402. 16 pins, 4 x 4 mm. Symmetry has it for $2.60.
John at J&S:
Bill: Do you think I could get away with just a transmitter at the sensor end? Any reason for the sensor to hear from the base station?Nordic took the 2401 transmitter section and made it the 2402. 16 pins, 4 x 4 mm. Symmetry has it for $2.60.
That’s really your call. I always use the transceiver just in case I
need communication the other way - for example to wake up
instrumentation from a lower-power sleep mode (CPU turns on the
receiver ever so often and looks for a packet to see if it needs
to wake up). You also might want to set some parameters like
sample rate remotely. Having said that, often I never use the
reverse direction and a transmitter would be fine.
Did you make a software flow chart that I can use? Do C programmers even use flowcharts?
I would like to write my MCU code in assembler, since I don’t know C.
John at J&S:
Did you make a software flow chart that I can use? Do C programmers even use flowcharts?I would like to write my MCU code in assembler, since I don’t know C.
I used the flow charts in the nRF2401 data sheet for shockburst
transmission and reception. You also need to load configuration
data after power-up. Make sure you use at least 16-bit-long
addresses.
Cypress CYWM6935 is a budget-limited ($9.75/ea. via www.digikey.com), FCC Type Certified, 2.7V to 3.6V, Industrial Temp, connect serial port at up to 2M, 2.4GHz RF module with range 50m outdoors LoS, 64kbps
Radio driver looks something like (origin is 8052)… ~1.5Kbytes of code space, ~70 bytes ram space:
#define SPI_WR 0x80
#define SPI_RD 0x00
#define SPI_INC 0x40
#define SPI_FRZ 0x00
// 0.65 is the implementation specific cal factor for DelayMicroSec();
#define SYNTH_SETTLE 200 * 0.65 // 200usec
#define PREAMBLE 32 * 0.65 // 32usec
#define RECEIVER_READY 35 * 0.65 // 35usec
#define CRYSTAL_STARTUP 2100 * 0.65 // 2100usec
#define RSSI_ADC_CONVERSION 50 * 0.65 // 50usec
#define tPD 10 * 0.65 // 10usec
#define tPWR_RST 1300 * 0.65 // 1300usec
#define tPDN_X13 2000 * 0.65 // 2000usec
#define tSPI_RDY 1 * 0.65 // 1usec
// RadioInit table
const BYTE code RadioInitTable[] =
{
0x20, 0x45, //REG_ANALOG_CTL
0x20, 0x44, //REG_ANALOG_CTL
0x2E, 0x80, //REG_PWR_CTL
0x26, 0xC0, //REG_VCO_CAL
0x33, 0x41, //REG_CLOCK_ENABLE
0x32, 0x41, //REG_CLOCK_MANUAL
0x24, 0x40, //REG_CRYSTAL_ADJ
0x06, 0x0B, //REG_SERDES_CTL
0x10, 0xFF, //REG_TX_VALID
0x04, 0x06, //REG_DATA_RATE - 64kbps, CODELEN=32, DATAMODE=DDR
0x19, 0x03, //REG_THRESHOLD_L - TH32=3
0x1A, 0x1D, //REG_THRESHOLD_H - TH32=3
0x11, 0xDC, //REG_PN_CODE, A overwrite default w/ PN Code Index 1 (64kbps table)
0x12, 0xC0, //REG_PN_CODE, A
0x13, 0x6B, //REG_PN_CODE, A
0x14, 0xB8, //REG_PN_CODE, A
0x15, 0x2B, //REG_PN_CODE, B
0x16, 0x09, //REG_PN_CODE, B
0x17, 0xBB, //REG_PN_CODE, B
0x18, 0xB2, //REG_PN_CODE, B
0x23, 0x05, //REG_PA - PA=5
0x21, 0x02 //REG_CHANNEL = 2402MHz
};
// RadioPnCode table
const BYTE code RadioPnCodeTable[] =
{
0x6A, 0xE7, 0x01, 0xEA, 0x03, 0xFD, 0x13, 0xD2, //PN Code 0
0xDC, 0xC0, 0x6B, 0xB8, 0x2B, 0x09, 0xBB, 0xB2, //PN Code 1
0xA3, 0x1E, 0xF2, 0xA4, 0x31, 0x32, 0x7A, 0xB3, //PN Code 2
0x44, 0x83, 0x3B, 0xDD, 0x14, 0xCF, 0x8E, 0xC9, //PN Code 3
0x35, 0x35, 0x4E, 0xC5, 0xF3, 0x52, 0x47, 0xB0, //PN Code 4
0x7C, 0x23, 0x8A, 0xCE, 0x45, 0x5C, 0x54, 0xD7, //PN Code 5
0x81, 0xAC, 0xFB, 0x83, 0x7A, 0x9A, 0x61, 0xAC, //PN Code 6
0x3C, 0x12, 0x5F, 0x9C, 0x39, 0x98, 0xF6, 0x8A //PN Code 7
};
BYTE radio_mid[] = {0,0,0,0};
// 16-bytes - data, data, data, data...
BYTE radio_txbuf[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F};
// 48-bytes - data, valid, rssi, data, valid, rssi...
BYTE radio_rxbuf[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
BYTE radio_rssi = 0;
BYTE radio_status[] = {0,0,0,0,0,0};
// 0 - REG_TX_INT_STAT
// 1 - SPARE
// 2 - REG_RX_INT_STAT
// 3 - REG_RX_DATA_A
// 4 - REG_RX_VALID_A
// 5 - REG_RSSI
// prototypes for radio snippets
void DelayMicroSec(WORD microsec);
void RadioReset(void);
void RadioInit(void);
void RadioSetPnCode(BYTE index);
void RadioGetMid(void);
BYTE RadioTransmit(BYTE len, BYTE *txbuf);
BYTE RadioReceive(BYTE *rxbuf);
void RadioSleep(void);
void RadioWake(void);
BYTE RadioGetRssi(void);
void DelayMicroSec(WORD microsec)
{
WORD i;
for(i=0;i<microsec;i++) {
// toggle SCK (w/o asserting nSS) to measure DelayMicroSec() w/scope
SCK_HI;
SCK_LO;
}
}
void RadioReset(void)
{
nRST_LO; nPD_LO; nSS_HI; SCK_LO;
DelayMicroSec(tPWR_RST); //1300usec min.
nPD_HI;
DelayMicroSec(tPDN_X13); //2000usec typ.
nRST_HI;
DelayMicroSec(tSPI_RDY); //1usec min.
nPD_HI;
DelayMicroSec(CRYSTAL_STARTUP); // ~Xmsec for crystal start to stable - idle
}
void RadioInit(void)
{
BYTE i;
for(i=0;i<sizeof(RadioInitTable);i+=2) {
SpiWrite(RadioInitTable[i],RadioInitTable[i+1]);
}
}
void RadioSetPnCode(BYTE index)
{
SpiFileWrite((SPI_INC | 0x11), 8, (&RadioPnCodeTable[0] + (8*index))); //REG_PN_CODE
}
void RadioGetMid(void)
{
SpiWrite((SPI_FRZ | 0x20), 0x64); //REG_ANALOG_CTL - enable reads from MID
SpiFileRead((SPI_INC | 0x3C), 4, &radio_mid[0]); //REG_MID - loaded into radio_mid[]
SpiWrite((SPI_FRZ | 0x20), 0x44); //REG_ANALOG_CTL - disable reads from MID
}
BYTE RadioTransmit(BYTE len, BYTE *txbuf)
{
BYTE i;
radio_status[0] = SpiRead((SPI_FRZ | 0x0E)); //REG_TX_INT_STAT - clear transmit status
SpiWrite((SPI_FRZ | 0x0D), 0x01); //REG_TX_INT_EN - enable empty flag on IRQ pin
SpiWrite((SPI_FRZ | 0x03), 0x50); //REG_CONTROL - enable tx
DelayMicroSec(SYNTH_SETTLE); // wait for synth to settle
DelayMicroSec(PREAMBLE); // delay in loading txbuf to send extra preamble symbol
for(i=0;i<len;i++) {
SpiWrite((SPI_FRZ | 0x0F), txbuf[i]); //REG_TX_DATA - send data
while(!IRQ); // wait 'til REG_TX_DATA empty
}
SpiWrite((SPI_FRZ | 0x0D), 0x02); //REG_TX_INT_EN - enable done flag on IRQ pin
while(!IRQ); // wait 'til REG_TX_DATA done
SpiWrite((SPI_FRZ | 0x03), 0x00); //REG_CONTROL - return to idle
radio_status[0] = SpiRead((SPI_FRZ | 0x0E)); //REG_TX_INT_STAT - clear transmit status
return(radio_status[0]);
}
BYTE RadioReceive(BYTE *rxbuf)
{
BYTE len;
BYTE i;
radio_status[2] = SpiRead((SPI_FRZ | 0x08)); //REG_RX_INT_STAT - clear receive status
SpiWrite((SPI_FRZ | 0x07), 0x03); //REG_RX_INT_EN - enable EOFA and FULLA flags on IRQ pin
SpiWrite((SPI_FRZ | 0x03), 0x90); //REG_CONTROL - enable rx
DelayMicroSec(SYNTH_SETTLE); // wait for synth to settle
DelayMicroSec(RECEIVER_READY); // wait for receiver afe ready
i = 0;
while(1)
{
while(!IRQ); // wait 'til either EOFA or FULLA receive flag fires
radio_status[2] = SpiRead((SPI_FRZ | 0x08)); //REG_RX_INT_STAT - check receive status
if(radio_status[2]&0x01)
{ //store REG_RX_DATA_A and REG_RX_VALID_A in user's rxbuf
SpiFileRead((SPI_INC | 0x09), 2, &rxbuf[i]);
if(rxbuf[i+1] > 3)
{
i += 2;
rxbuf[i] = SpiRead((SPI_FRZ | 0x22)); // store REG_RSSI in user's rxbuf
i++; // ~75usec of "idle" time between bytes when using 64kbps
}
}
if(radio_status[2]&0x02 && i) break;
}
SpiWrite((SPI_FRZ | 0x03), 0x00); //REG_CONTROL - return to idle
len = i;
return(len);
}
void RadioSleep(void)
{
SpiWrite((SPI_FRZ | 0x03), 0x00); //REG_CONTROL - force idle
nPD_LO; // force sleep
DelayMicroSec(tPD); //10usec
// typically takes ~50usec from the time nPD is asserted to low power mode
}
void RadioWake(void)
{
nPD_HI; // force idle
DelayMicroSec(CRYSTAL_STARTUP); // ~Xmsec for crystal start to stable - idle
}
BYTE RadioGetRssi(void)
{
SpiWrite((SPI_FRZ | 0x2F), 0x80); //REG_CARRIER_DETECT - force radio to manually acquire rssi reading
SpiWrite((SPI_FRZ | 0x03), 0x90); //REG_CONTROL - put radio in receive mode - triggers rssi adc
DelayMicroSec(SYNTH_SETTLE); // wait for synth to settle
DelayMicroSec(RECEIVER_READY); // wait for receiver ready
DelayMicroSec(RSSI_ADC_CONVERSION); // wait for 5-bit rssi adc to complete
radio_status[5] = SpiRead((SPI_FRZ | 0x22)); //REG_RSSI - flush stale rssi reading
DelayMicroSec(RSSI_ADC_CONVERSION); // wait for 5-bit rssi adc to complete
radio_status[5] = SpiRead((SPI_FRZ | 0x22)); //REG_RSSI - get rssi reading
SpiWrite((SPI_FRZ | 0x2F), 0x00); //REG_CARRIER_DETECT - manually clear CDET
SpiWrite((SPI_FRZ | 0x03), 0x00); //REG_CONTROL - put radio in idle mode
return(radio_status[5]);
}
Fixed bug in RadioGetRssi() - the final SpiWrite should be writing 0x00 to register 0x03, not 0x90.