Hi all. This is my first post. I didn’t have much luck searching the forums, but please feel free to refer me to previous posts.
I’m having issues interfacing my SFE TX/RX modules to my other circuitry. Can anybody tell me what type of interface the TX module’s data pin expects, and what the RX module’s data pin will put out? That is, does the TX module expect RS232 logic levels? Does the RX module output RS232 levels, or is it something else, such as TTL logic levels? Also, is the stated baud rate just the maximum supported, or do I have to use that exact baud rate?
My goal is to send a very small amount of data (less than 100 bits) several times per day. The data will come from an FPGA’s serial port, and at the receiver I need to interface to a parallel port on a Windows PC.
Also, when I searched the forums, I saw somebody mention a “RF-KLP-315 basics thread” - can anybody point me to that thread? I couldn’t find it using the Search feature.
They use logic level inputs and outputs, not RS-232. You will probably need Manchester code to get them to work properly. Try sending ‘U’ continuously and see if you can receive it - this has a constant DC level.
The listed baud rate the the Maximum. You may use lower baud rates.
Also these use OOK modulation so you really should do something like Manchester encoding and need to start you transmission with a couple of sync bytes so the receiver can ‘lock in’.
In the Electronical Characteristics table (page 2 of Data Sheets ):
Rec:
ASK out logic HIGH Min = 0.7*Vcc, LOW Max = 0.3 *Vcc
I’ve had success using these same modules. I’d be glad to post my C code if you’re interested. The library is for a PIC microcontroller, but the basic ideas should be portable to any TTL device. I used something akin to Manchester encoding to get it working, with a sync byte at the start of the data transfer. In my experience, 600 bits per second has given me the longest range with the fewest errors (tried it out to 50+ feet so far, still had a reliable signal). 300 bps and 1200 also work, but they don’t seem to transmit as far. As long as you transition between +5V / +0V on the transmit line at least once every 30 milliseconds, it should be OK. If you hold the voltage for too long, the automatic gain control on the receiver will drift away and you’ll need to send a series of +5V / +0V / +5V transitions to get the receiver’s attention back.
I’ve also just started working with this RF pair and haven’t had luck getting them to work. Not too familiar with coding so is it possible to get your code?
Does anybody know if applying -5V to the transmitter’s data pin will damage it? And if not, will -5V be interpreted as a TTL low by the TX? I’m going to connect a serial port to the transmitter, so the input logic will be -5V = high and +5V = low. At the receiver’s data output, the logic inversion and the TTL logic levels are not a problem, but I don’t want to fry the TX with a negative voltage on the data pin. Do I need to use a logic level converter for the TX data input?
I’ve looked over the TX data sheet, and it’s not too helpful (although it does give the minimum baud rate, so shame on me for overlooking that). As waltr posted above, the RX datasheet gives the output levels, but the TX datasheet doesn’t tell me what the input levels need to be.
I wouldn’t put -5V on the data line… usually the absolute minimum is only -0.3V or so. But there’s lots of ways to get your signal into the +0V to +5V range that this unit requires.
This is the receiver program, also using a PIC16F630:
#include <htc.h>
#pragma warning disable 750
#define OUTPUT 0
#define INPUT 1
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000
#endif
/* At a TMR0 1:8 prescaler, 200 ticks = 600 baud */
/* This has been tested to about 50 feet, and seems to work fairly well. */
#define RS232_BIT_TIMER_TICKS 200
typedef unsigned char uchar;
/* Motor control output pins */
#define motorctl_a_tris TRISC2
#define motorctl_a_pin RC2
#define motorctl_b_tris TRISC3
#define motorctl_b_pin RC3
/* ASK radio receiver pin */
#define ask_receiver RC4
/* "Signal Good" LED pin */
#define good_signal_tris TRISC1
#define good_signal_led RC1
#define good_signal_vss_tris TRISC0
/* Interrupt level **************************************************/
void interrupt kill_switch(void)
/* In the event of a signal loss, it will stop the motors and
* turn off the signal_good LED. */
{
if (TMR1IE && TMR1IF)
{
/* Acknowledge TIMER1 interrupt */
TMR1IF = 0;
/* Turn off the "good signal" LED */
good_signal_led = 0;
/* Turn off both motors */
motorctl_a_pin = 0;
motorctl_b_pin = 0;
}
}
/* Level 2 **********************************************************/
void pause(unsigned int ms)
{
while (ms-- > 0)
__delay_us(999);
}
void wait_tmr0(uchar stop_time)
/* Pause until the timer TMR0 reaches the given stop_time, then reset
* the timer. Make sure TIMER0 is running before calling this. */
{
while (TMR0 < stop_time) ;
TMR0 = 0;
}
void ASK_listen_sync()
/* Attempt to gain ASK synchronization. It will look for the sync code of
* many 1s followed by the start bit 0 on the ask_receiver input pin. The
* function returns when a signal is found and the first data bit is on
* the input pin. */
{
const uchar sync_code_len = 10;
const uchar sync_code[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 0};
uchar got_sync = 0;
uchar bit_count = 0;
uchar retries = 0;
/* Reset the "kill switch" timer to zero */
TMR1H = 0;
TMR1L = 0;
bit_count = 0;
while (!got_sync)
{
while (ask_receiver != sync_code[bit_count])
; /* keep waiting for the first bit */
/* Got the first bit - reset the timer here */
TMR0 = 0;
bit_count = 1;
/* Try to position our reads in the center of the sender's output phase */
wait_tmr0(RS232_BIT_TIMER_TICKS / 2);
/* Listen for the rest of the bits */
while ((bit_count >= 1) && (!got_sync))
{
wait_tmr0(RS232_BIT_TIMER_TICKS);
if (ask_receiver != sync_code[bit_count])
bit_count = 0; /* Lost the signal - try again. */
else
{
++bit_count;
if (bit_count == sync_code_len)
got_sync = 1; /* Found it! */
}
}
}
}
void ASK_receive_4bit(uchar* word)
{
uchar bit_count;
uchar input = 0;
for (bit_count = 0; bit_count < 4; bit_count++)
{
wait_tmr0(RS232_BIT_TIMER_TICKS);
input = (input * 2) + ask_receiver;
}
wait_tmr0(RS232_BIT_TIMER_TICKS); /* Parity bit */
*word = input;
}
/* Level 2 **********************************************************/
void set_motor_power(uchar ask_data)
{
uchar ctl_value = 0;
/* Eventually, the plan is to have full bi-directional motor control. With
an H-bridge or similar, the following code would give tristate control
over two motors.
motorctl_aa = !((ask_data & 0x8) >> 3);
motorctl_ab = (ask_data & 0x4) >> 2;
motorctl_ba = !((ask_data & 0x2) >> 1);
motorctl_bb = (ask_data & 0x1);
*/
/* But for now, just move forward if any movement is requested. */
ctl_value = ((ask_data & 0x8) >> 3) ^ ((ask_data & 0x4) >> 2);
motorctl_a_pin = ctl_value;
ctl_value = ((ask_data & 0x2) >> 1) ^ ((ask_data & 0x1));
motorctl_b_pin = ctl_value;
}
/* Level 1 **********************************************************/
void read_and_execute_cmd(void)
{
uchar ask_data;
ASK_listen_sync();
good_signal_led = 1;
ASK_receive_4bit(&ask_data);
set_motor_power(ask_data);
}
void setup_timer0(void)
{
/* Put TIMER0 into TIMER mode (counts using internal clock. External
* clock signals and pins will be ignored. */
T0CS = 0;
/* Set the pre-scaler to 1:8 */
PSA = 0;
PS2 = 0;
PS1 = 1;
PS0 = 0;
/* Reset the timer */
TMR0 = 0;
}
void setup_io_pins(void)
{
/* Set up the "good signal" LED */
good_signal_tris = OUTPUT;
good_signal_vss_tris = OUTPUT;
/* Set motor H-bridge control pins as outputs */
motorctl_a_tris = OUTPUT;
motorctl_b_tris = OUTPUT;
/* Lamp test */
good_signal_led = 1;
pause(300);
good_signal_led = 0;
pause(300);
}
void setup_timer1()
{
/* Reset the timer to zero */
TMR1H = 0;
TMR1L = 0;
/* Set up the timer1 configuration and start the timer */
/* TMR1GE=0, T1CKPS=11, T1OSCEN=0, T1SYNC=1, TMR1CS=0, TMR1ON=1 */
T1CON = 0x35;
/* Set the Timer1 Interrupt Enable flag */
TMR1IF = 0; /* Acknowledge any prior interrupt */
TMR1IE = 1; /* Unmask the TIMER1 interrupt */
/* Unmask the timer peripheral device interrupt */
PIE1 = PIE1 | 0x01;
/* Enable peripherial device interrupts */
PEIE = 1;
}
/* Main Level *******************************************************/
int main(void)
{
setup_io_pins();
setup_timer0();
setup_timer1();
GIE = 1; /* Enable interrupts */
while (-1)
read_and_execute_cmd();
return 0;
}