virtualwire not decoding data

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear freaks

 

I just ported the virtualwire library from Arduino to AVR platform and seperated the Tx & Rx functions.In the Tx side,I am using ATTINY45@8MHz and on the receiver side,i am using ATMEGA328p@16MHz.The transmitter is emitting data (I can see in my DSO) but the receiver isn't decoding.The problem is that,There is no display on the Serial terminal.Also the LED of the receiver side is not flashing on receiving message.I also checked that both the ISRs are firing at the same time interval that means the timing calculations are correct for both the CPUs at different clock speeds.I tried with 433 MHz RF modules and also with direct connection with a wire with common ground between two CPUs.

 

The Tx & Rx codes are as follows

 

Tx virtualwire.h file is as follows:

 

#ifndef _VIRTUALWIRE_H
#define _VIRTUALWIRE_H

#ifndef F_CPU
#define F_CPU 8000000UL
#endif

#include <avr/io.h>
#include <util/crc16.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <string.h>

#define vw_ddr DDRB
#define vw_port PORTB
#define vw_pin PINB
#define LED 2

#define true 1
#define false 0

#define VW_MAX_MESSAGE_LEN 30
#define VW_MAX_PAYLOAD VW_MAX_MESSAGE_LEN-3
#define VW_RX_RAMP_LEN 160
#define VW_RX_SAMPLES_PER_BIT 8
#define VW_RAMP_INC (VW_RX_RAMP_LEN/VW_RX_SAMPLES_PER_BIT)
#define VW_RAMP_TRANSITION VW_RX_RAMP_LEN/2
#define VW_RAMP_ADJUST 9
#define VW_RAMP_INC_RETARD (VW_RAMP_INC-VW_RAMP_ADJUST)
#define VW_RAMP_INC_ADVANCE (VW_RAMP_INC+VW_RAMP_ADJUST)
#define VW_HEADER_LEN 8

void vw_set_tx_pin(uint8_t pin);
void vw_setup(uint16_t speed);
uint8_t vx_tx_active();
void vw_wait_tx();
uint8_t vw_send(uint8_t* buf, uint8_t len);

#endif

 

Tx virtualwire.c is as follows

 

#include "VirtualWire.h"

static uint8_t vw_tx_buf[(VW_MAX_MESSAGE_LEN * 2) + VW_HEADER_LEN]
     = {0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x38, 0x2c};
static uint8_t vw_tx_len = 0;
static uint8_t vw_tx_index = 0;
static uint8_t vw_tx_bit = 0;
static uint8_t vw_tx_sample = 0;
static volatile uint8_t vw_tx_enabled = 0;
static uint16_t vw_tx_msg_count = 0;
static uint8_t vw_tx_pin;
static uint8_t symbols[] =
{
    0xd,  0xe,  0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c,
    0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x32, 0x34
};

uint16_t vw_crc(uint8_t *ptr, uint8_t count)
{
    uint16_t crc = 0xffff;

    while (count-- > 0)
    crc = _crc_ccitt_update(crc, *ptr++);
    return crc;
}

uint8_t vw_symbol_6to4(uint8_t symbol)
{
    uint8_t i;
    
    // Linear search :-( Could have a 64 byte reverse lookup table?
    for (i = 0; i < 16; i++)
    if (symbol == symbols[i]) return i;
    return 0; // Not found
}

void vw_set_tx_pin(uint8_t pin)
{
    vw_tx_pin = pin;
}

static uint8_t _timer_calc(uint16_t speed, uint16_t max_ticks, uint16_t *nticks)
{
    // Clock divider (prescaler) values - 0/3333: error flag
    uint16_t prescalers[] = {0, 1, 8, 64, 256, 1024, 3333};
    uint8_t prescaler=0; // index into array & return bit value
    unsigned long ulticks; // calculate by ntick overflow

    // Div-by-zero protection
    if (speed == 0)
    {
        // signal fault
        *nticks = 0;
        return 0;
    }

    // test increasing prescaler (divisor), decreasing ulticks until no overflow
    for (prescaler=1; prescaler < 7; prescaler += 1)
    {
        // Amount of time per CPU clock tick (in seconds)
        float clock_time = (1.0 / ((float)(F_CPU) / (float)(prescalers[prescaler])));
        // Fraction of second needed to xmit one bit
        float bit_time = ((1.0 / (float)(speed)) / 8.0);
        // number of prescaled ticks needed to handle bit time @ speed
        ulticks = (long)(bit_time / clock_time);
        // Test if ulticks fits in nticks bitwidth (with 1-tick safety margin)
        if ((ulticks > 1) && (ulticks < max_ticks))
        {
            break; // found prescaler
        }
        // Won't fit, check with next prescaler value
    }

    // Check for error
    if ((prescaler == 6) || (ulticks < 2) || (ulticks > max_ticks))
    {
        // signal fault
        *nticks = 0;
        return 0;
    }

    *nticks = ulticks;
    return prescaler;
}

void vw_setup(uint16_t speed)
{
    uint16_t nticks; // number of prescaled ticks needed
    uint8_t prescaler; // Bit values for CS0[2:0]

 // figure out prescaler value and counter match value
    prescaler = _timer_calc(speed, (uint8_t)-1, &nticks);
    if (!prescaler)
    {
        return; // fault
    }

    TCCR0A = 0;
    TCCR0A = _BV(WGM01); // Turn on CTC mode / Output Compare pins disconnected

    // convert prescaler index to TCCRnB prescaler bits CS00, CS01, CS02
    TCCR0B = 0;
    TCCR0B = prescaler; // set CS00, CS01, CS02 (other bits not needed)

    // Number of ticks to count before firing interrupt
    OCR0A = (uint8_t)(nticks);

    // Set mask to fire interrupt when OCF0A bit is set in TIFR0
    TIMSK |= _BV(OCIE0A);

vw_ddr |= (1<<vw_tx_pin);
vw_port &= ~(1<<vw_tx_pin);
}

void vw_tx_start()
{
    vw_tx_index = 0;
    vw_tx_bit = 0;
    vw_tx_sample = 0;
    vw_tx_enabled = true;
}

void vw_tx_stop()
{
    vw_port &= ~(1<<vw_tx_pin);
    vw_tx_enabled = false;
}

uint8_t vx_tx_active()
{
    return vw_tx_enabled;
}

void vw_wait_tx()
{
    while (vw_tx_enabled);
    
}

uint8_t vw_send(uint8_t* buf, uint8_t len)
{
    uint8_t i;
    uint8_t index = 0;
    uint16_t crc = 0xffff;
    uint8_t *p = vw_tx_buf + VW_HEADER_LEN; // start of the message area
    uint8_t count = len + 3; // Added byte count and FCS to get total number of bytes

    if (len > VW_MAX_PAYLOAD)
    return false;

    // Wait for transmitter to become available
    vw_wait_tx();

    // Encode the message length
    crc = _crc_ccitt_update(crc, count);
    p[index++] = symbols[count >> 4];
    p[index++] = symbols[count & 0xf];

    // Encode the message into 6 bit symbols. Each byte is converted into
    // 2 6-bit symbols, high nybble first, low nybble second
    for (i = 0; i < len; i++)
    {
    crc = _crc_ccitt_update(crc, buf[i]);
    p[index++] = symbols[buf[i] >> 4];
    p[index++] = symbols[buf[i] & 0xf];
    }

    // Append the fcs, 16 bits before encoding (4 6-bit symbols after encoding)
    // Caution: VW expects the _ones_complement_ of the CCITT CRC-16 as the FCS
    // VW sends FCS as low byte then hi byte
    crc = ~crc;
    p[index++] = symbols[(crc >> 4)  & 0xf];
    p[index++] = symbols[crc & 0xf];
    p[index++] = symbols[(crc >> 12) & 0xf];
    p[index++] = symbols[(crc >> 8)  & 0xf];

    // Total number of 6-bit symbols to send
    vw_tx_len = index + VW_HEADER_LEN;

    // Start the low level interrupt handler sending symbols
    vw_tx_start();

    return true;
}

ISR (TIMER0_COMPA_vect)
{
    if (vw_tx_enabled && vw_tx_sample++ == 0)
    {
    // Send next bit
    // Symbols are sent LSB first
    // Finished sending the whole message? (after waiting one bit period
    // since the last bit)
    if (vw_tx_index >= vw_tx_len)
    {
        vw_tx_stop();
        vw_tx_msg_count++;
    }
    else
    {
       // digitalWrite(vw_tx_pin, vw_tx_buf[vw_tx_index] & (1 << vw_tx_bit++));
       if(vw_tx_buf[vw_tx_index] & (1 << vw_tx_bit++))
       {
           vw_port |= (1<<vw_tx_pin);
       }
       else
       {
           vw_port &= ~(1<<vw_tx_pin);
       }
       
        if (vw_tx_bit >= 6)
        {
        vw_tx_bit = 0;
        vw_tx_index++;
        }
    }
    }
    if (vw_tx_sample > 7)
    vw_tx_sample = 0;
   }

 

Tx main is as follows:

 

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include "VirtualWire.h"

int main(void)
{
    DDRB |= (1<<LED);
    vw_set_tx_pin(3);
    vw_setup(500);
    sei();
        
    while (1)
    {
        char *msg = "Test";
        vw_send((uint8_t *)msg, strlen(msg));
        vw_wait_tx();
        PORTB ^= (1<<LED);
        _delay_ms(1000);
        
    }
}

 

Now code for the receiver side.

 

Rx virtualwire.h file is as follows:

 

#ifndef _VIRTUALWIRE_H
#define _VIRTUALWIRE_H

#ifndef F_CPU
#define F_CPU 16000000UL
#endif

#include <avr/io.h>
#include <util/crc16.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <string.h>

#define vw_ddr DDRD
#define vw_port PORTD
#define vw_pin PIND
#define LED 5

#define true 1
#define false 0

#define VW_MAX_MESSAGE_LEN 30
#define VW_MAX_PAYLOAD VW_MAX_MESSAGE_LEN-3
#define VW_RX_RAMP_LEN 160
#define VW_RX_SAMPLES_PER_BIT 8
#define VW_RAMP_INC (VW_RX_RAMP_LEN/VW_RX_SAMPLES_PER_BIT)
#define VW_RAMP_TRANSITION VW_RX_RAMP_LEN/2
#define VW_RAMP_ADJUST 9
#define VW_RAMP_INC_RETARD (VW_RAMP_INC-VW_RAMP_ADJUST)
#define VW_RAMP_INC_ADVANCE (VW_RAMP_INC+VW_RAMP_ADJUST)
#define VW_HEADER_LEN 8

void vw_set_rx_pin(uint8_t pin);
void vw_setup(uint16_t speed);
void vw_rx_start();
void vw_rx_stop();
void vw_wait_rx();
uint8_t vw_have_message();
uint8_t vw_get_message(uint8_t* buf, uint8_t* len);

#endif

 

Rx virtualwire.c is as follows:

 

#include "VirtualWire.h"

static uint8_t vw_rx_pin;
static uint8_t vw_rx_sample = 0;
static uint8_t vw_rx_last_sample = 0;
static uint8_t vw_rx_pll_ramp = 0;
static uint8_t vw_rx_integrator = 0;
static uint8_t vw_rx_active = 0;
static volatile uint8_t vw_rx_done = 0;
static uint8_t vw_rx_enabled = 0;
static uint16_t vw_rx_bits = 0;
static uint8_t vw_rx_bit_count = 0;
static uint8_t vw_rx_buf[VW_MAX_MESSAGE_LEN];
static uint8_t vw_rx_count = 0;
static volatile uint8_t vw_rx_len = 0;
static uint8_t vw_rx_bad = 0;
static uint8_t vw_rx_good = 0;
static uint8_t symbols[] =
{
    0xd,  0xe,  0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c,
    0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x32, 0x34
};

uint16_t vw_crc(uint8_t *ptr, uint8_t count)
{
    uint16_t crc = 0xffff;

    while (count-- > 0)
    crc = _crc_ccitt_update(crc, *ptr++);
    return crc;
}

uint8_t vw_symbol_6to4(uint8_t symbol)
{
    uint8_t i;
    
    // Linear search :-( Could have a 64 byte reverse lookup table?
    for (i = 0; i < 16; i++)
    if (symbol == symbols[i]) return i;
    return 0; // Not found
}

void vw_set_rx_pin(uint8_t pin)
{
    vw_rx_pin = pin;
}

void vw_pll()
{
    // Integrate each sample
    if (vw_rx_sample)
    vw_rx_integrator++;

    if (vw_rx_sample != vw_rx_last_sample)
    {
        // Transition, advance if ramp > 80, retard if < 80
        vw_rx_pll_ramp += ((vw_rx_pll_ramp < VW_RAMP_TRANSITION)
        ? VW_RAMP_INC_RETARD
        : VW_RAMP_INC_ADVANCE);
        vw_rx_last_sample = vw_rx_sample;
    }
    else
    {
        // No transition
        // Advance ramp by standard 20 (== 160/8 samples)
        vw_rx_pll_ramp += VW_RAMP_INC;
    }
    if (vw_rx_pll_ramp >= VW_RX_RAMP_LEN)
    {
        // Add this to the 12th bit of vw_rx_bits, LSB first
        // The last 12 bits are kept
        vw_rx_bits >>= 1;

        // Check the integrator to see how many samples in this cycle were high.
        // If < 5 out of 8, then its declared a 0 bit, else a 1;
        if (vw_rx_integrator >= 5)
        vw_rx_bits |= 0x800;

        vw_rx_pll_ramp -= VW_RX_RAMP_LEN;
        vw_rx_integrator = 0; // Clear the integral for the next cycle

        if (vw_rx_active)
        {
            // We have the start symbol and now we are collecting message bits,
            // 6 per symbol, each which has to be decoded to 4 bits
            if (++vw_rx_bit_count >= 12)
            {
                // Have 12 bits of encoded message == 1 byte encoded
                // Decode as 2 lots of 6 bits into 2 lots of 4 bits
                // The 6 lsbits are the high nybble
                uint8_t this_byte =
                (vw_symbol_6to4(vw_rx_bits & 0x3f)) << 4
                | vw_symbol_6to4(vw_rx_bits >> 6);

                // The first decoded byte is the byte count of the following message
                // the count includes the byte count and the 2 trailing FCS bytes
                // REVISIT: may also include the ACK flag at 0x40
                if (vw_rx_len == 0)
                {
                    // The first byte is the byte count
                    // Check it for sensibility. It cant be less than 4, since it
                    // includes the bytes count itself and the 2 byte FCS
                    vw_rx_count = this_byte;
                    if (vw_rx_count < 4 || vw_rx_count > VW_MAX_MESSAGE_LEN)
                    {
                        // Stupid message length, drop the whole thing
                        vw_rx_active = false;
                        vw_rx_bad++;
                        return;
                    }
                }
                vw_rx_buf[vw_rx_len++] = this_byte;

                if (vw_rx_len >= vw_rx_count)
                {
                    // Got all the bytes now
                    vw_rx_active = false;
                    vw_rx_good++;
                    vw_rx_done = true; // Better come get it before the next one starts
                }
                vw_rx_bit_count = 0;
            }
        }
        // Not in a message, see if we have a start symbol
        else if (vw_rx_bits == 0xb38)
        {
            // Have start symbol, start collecting message
            vw_rx_active = true;
            vw_rx_bit_count = 0;
            vw_rx_len = 0;
            vw_rx_done = false; // Too bad if you missed the last message
        }
    }
}

static uint8_t _timer_calc(uint16_t speed, uint16_t max_ticks, uint16_t *nticks)
{
    // Clock divider (prescaler) values - 0/3333: error flag
    uint16_t prescalers[] = {0, 1, 8, 64, 256, 1024, 3333};
    uint8_t prescaler=0; // index into array & return bit value
    unsigned long ulticks; // calculate by ntick overflow

    // Div-by-zero protection
    if (speed == 0)
    {
        // signal fault
        *nticks = 0;
        return 0;
    }

    // test increasing prescaler (divisor), decreasing ulticks until no overflow
    for (prescaler=1; prescaler < 7; prescaler += 1)
    {
        // Amount of time per CPU clock tick (in seconds)
        float clock_time = (1.0 / ((float)(F_CPU) / (float)(prescalers[prescaler])));
        // Fraction of second needed to xmit one bit
        float bit_time = ((1.0 / (float)(speed)) / 8.0);
        // number of prescaled ticks needed to handle bit time @ speed
        ulticks = (long)(bit_time / clock_time);
        // Test if ulticks fits in nticks bitwidth (with 1-tick safety margin)
        if ((ulticks > 1) && (ulticks < max_ticks))
        {
            break; // found prescaler
        }
        // Won't fit, check with next prescaler value
    }

    // Check for error
    if ((prescaler == 6) || (ulticks < 2) || (ulticks > max_ticks))
    {
        // signal fault
        *nticks = 0;
        return 0;
    }

    *nticks = ulticks;
    return prescaler;
}

void vw_setup(uint16_t speed)
{
    uint16_t nticks; // number of prescaled ticks needed
    uint8_t prescaler; // Bit values for CS0[2:0]

    prescaler = _timer_calc(speed, (uint16_t)-1, &nticks);

    if (!prescaler)
    {
        return; // fault
    }

    TCCR1A = 0; // Output Compare pins disconnected
    TCCR1B = _BV(WGM12); // Turn on CTC mode

    // convert prescaler index to TCCRnB prescaler bits CS10, CS11, CS12
    TCCR1B |= prescaler;

    // Caution: special procedures for setting 16 bit regs
    // is handled by the compiler
    OCR1A = nticks;
    // Enable interrupt

    TIMSK1 |= _BV(OCIE1A);

    vw_ddr &= ~(1<<vw_rx_pin);
    vw_port &= ~(1<<vw_rx_pin);
    
}

void vw_rx_start()
{
    if (!vw_rx_enabled)
    {
    vw_rx_enabled = true;
    vw_rx_active = false; // Never restart a partial message
    }
}

void vw_rx_stop()
{
    vw_rx_enabled = false;
}

void vw_wait_rx()
{
    while (!vw_rx_done)
    ;
}

uint8_t vw_have_message()
{
    return vw_rx_done;
}

uint8_t vw_get_message(uint8_t* buf, uint8_t* len)
{
    uint8_t rxlen;
    
    // Message available?
    if (!vw_rx_done)
    return false;
    
    // Wait until vw_rx_done is set before reading vw_rx_len
    // then remove bytecount and FCS
    rxlen = vw_rx_len - 3;
    
    // Copy message (good or bad)
    if (*len > rxlen)
    *len = rxlen;
    memcpy(buf, vw_rx_buf + 1, *len);
    
    vw_rx_done = false; // OK, got that message thanks
    
    // Check the FCS, return goodness
    return (vw_crc(vw_rx_buf, vw_rx_len) == 0xf0b8); // FCS OK?
}

ISR (TIMER1_COMPA_vect)
{
    if (vw_rx_enabled)
    {
    if(bit_is_set(vw_pin,vw_rx_pin))
    {
        vw_rx_sample = 1;
    }
    else
    {
        vw_rx_sample = 0;
    }
    }
    if (vw_rx_enabled)
    vw_pll();
}

 

Rx main is as follows:

 

#include <avr/io.h>
#include <util/delay.h>
#include <avr/cpufunc.h>
#include <avr/interrupt.h>
#include "uart.h"
#include "VirtualWire.h"

#define LED 5

int main(void)
{
    
    DDRB |= (1<<LED);
    sei();
    
    uart_init();
    vw_set_rx_pin(7);
    vw_setup(500);
    vw_rx_start();
    
    
    while (1)
    {
    
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;
    
    if (vw_get_message(buf, &buflen)) // Non-blocking
    {
        PORTB ^= _BV(LED);
        int i;
        for (i = 0;i < buflen;i++ )
    {
        uart_send(buf[i]);
        uart_sendstring("\r\n");
    }
    }
    
    }
}

 

 

Any type of help is appreciated to make it work.

 

 

 

 

 

 

 

 

Last Edited: Sun. Feb 12, 2017 - 04:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

how do you know you 'ported' it correctly? I'd suggest you validate your changes by using the Arduino version and use that to test your rx and tx versions. It could be your porting effort is faulty thus both ends could be failing. It could be your radio modules are defective. Narrow down the defect space.

 

1. Assuming the Arduino version is known good - construct rx and tx using arduino code. This will verify your basic hardware setup works. If this doesn't work, then find out what the problem is.

2. assuming #1 test works, substitute the rx end with your setup. Verify this works.

3. assuming #1 test works, substitute the rx end with your setup. Verify this works.

If tests #2,3 don't work - then you better look carefully at your 'porting' effort.

Also - you've been here long enough - use the <> button in the toolbar to post your code so we can read it.

Last Edited: Sat. Feb 11, 2017 - 01:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The decoding should work with a direct wire connection between the Tx & Rx with a common ground.Isn't it??

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SHARANYADAS wrote:

The decoding should work with a direct wire connection between the Tx & Rx with a common ground.Isn't it??

 

How do we know this? You currently have too many unknowns - unless there's some you're not telling us?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok,I tested the receiver side with Arduino code as stated in the virtualwire website(Only with the pin nos altered)....but that is also not decoding!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:

how do you know you 'ported' it correctly? I'd suggest you validate your changes by using the Arduino version and use that to test your rx and tx versions. It could be your porting effort is faulty thus both ends could be failing. It could be your radio modules are defective. Narrow down the defect space.

 

1. Assuming the Arduino version is known good - construct rx and tx using arduino code. This will verify your basic hardware setup works. If this doesn't work, then find out what the problem is.

2. assuming #1 test works, substitute the rx end with your setup. Verify this works.

3. assuming #1 test works, substitute the rx end with your setup. Verify this works.

If tests #2,3 don't work - then you better look carefully at your 'porting' effort.

Also - you've been here long enough - use the <> button in the toolbar to post your code so we can read it.

 

seems the problem is in the Tx side.I followed the steps as you said

 

1)Rebuilt both hardwares with atmega328p and coded in arduino environment(Worked).

2)Burnt my ported library(AVR compatible) in the Rx side and still it is working.So the problem seems in the ATTINY45 Tx side(Although I am using ATMEGA328P in the Tx for troubleshooting).

Now I will burn the ported Tx code in the atmega328p in the Tx side and if it works,then i will change & then burn the Tx code finally into ATTINY45.

Thanks a lot for the troubleshooting technique.Will let you know what happens next......

Last Edited: Sat. Feb 11, 2017 - 06:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok...now both of my atmega328ps are communicating using 433Mhz RF modules with ported code.so the code part is ok.....last experiment remains....i.e changing the Tx uC to ATTINY45.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The Attiny45@8MHz at the Tx side and Atmega328p@16Mhz on the Rx side is only communicationg at 2500 bps.....strange!!Any idea....anyone?????
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You've not told us if 2500bps is high or low - please don't assume we know this. What logical debug technique would you apply to this problem?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is your t45 running from the internal RC oscillator?  Note that it has a factory tolerance of about +/- 10%, although it's likely to be within 2% or so.  That's on the edge of what the VirtualWire protocol can handle.  You'll have more trouble at higher bit rates.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
You've not told us if 2500bps is high or low - please don't assume we know this. What logical debug technique would you apply to this problem?

 

As per the documentation,it can be as higher 7000bps without error.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:

Is your t45 running from the internal RC oscillator?  Note that it has a factory tolerance of about +/- 10%, although it's likely to be within 2% or so.  That's on the edge of what the VirtualWire protocol can handle.  You'll have more trouble at higher bit rates.

 

I also tried with different lower bitrate as 200/500/1000 etc....but these are also not working!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It may yet be due to RC calibration.  I've ported the same protocol VW is based on for my own uses, and although the RX has a nifty PLL for locking on to a signal, it is still inherently sensitive to speed differential between RX and TX.  I suggest you calibrate the t45, or better yet run it on a crystal or external clock to see if the problem persists.  You could simply program the CKOUT fuse on the 328P and connect it's CLKO pin to the t45's XTAL1 pin, programming the t45's fuses to use an external clock.  Or if you want to run the t45 at 8 MHz instead of 16 MHz, use a PWM output on a timer on the328P instead of CLKO.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Sun. Feb 12, 2017 - 07:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok....the problem is detected!!!!!!The internal RC oscillator of the Attiny45 was the cause of the problem.Now I'm running the Tx circuit with External 8MHz crystal and varied the BPS from as low as 500 to as high as 6000 and there was no problem regarding decoding(Although I am directly connected from Tx to Rx with a wire!!).

I also programmed the CKOUT fuse of the Attiny45 and saw that the internal clock was varying from 8.403 to 8.547 MHz while on the Internal RC whereas while running on external 8 MHz crystal,the clock is varying between 7.90Mhz to 8.16Mhz.

So....should I proceed with calibrating the internl RC clock or should I use external crystal??By d way....thanks a lot to both of you!!!heartheartyesyes

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

8.403 to 8.547 MHz while on the Internal RC

Not surprising, since that's between +5% and +7% of nominal, well within the spec'd +/- 10%.  Note that the factory calibration is done at 3V and 25C.  If you're running at a different voltage or temperature you can expect different results.

 

whereas while running on external 8 MHz crystal,the clock is varying between 7.90Mhz to 8.16Mhz.

That >>is<< surprising.  Clock stability with an crystal should be very much better than that.  Those numbers amount to +2/-1.25%.  That's several orders of magnitude higher than it should be.  Either your crystal is bad, or you haven't hooked it up correctly, or you aren't measuring it correctly.  The crystal and its capacitors must be as physically close to the t45 as possible, with no other components sharing the ground trace used by the caps.  What value caps are you using?

 

should I proceed with calibrating the internl RC clock or should I use external crystal??

That's up to you.  A crystal should be more accurate and stable (your strange results above notwithstanding).  If you can spare the pins, use the crystal.  However, note that the crystal is slower to start up and can use more power than the internal RC.  If this is going to be a battery powered app which spends most of its time in deep sleep, you'll want to consider that.

 

EDIT:

Another option is to calibrate the RX end.  In my own library, I monitor the action of the PLL during reception of the preamble and start symbol, and then adjust the period of the timer used for sampling ISR.  This allows it to zero in on the real TX frequency.  It isn't perfect.  If the TX frequency is too far outside the target frequency then a start symbol may never be reliably detected to begin with.  Also, if the link is especially noisy then any false positives for a start symbol can steer the monitor in the wrong direction.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Sun. Feb 12, 2017 - 05:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:
The crystal and its capacitors must be as physically close to the t45 as possible, with no other components sharing the ground trace used by the caps. What value caps are you using?

 

I am not using any caps and everything is hooked up at breadboard!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am not using any caps and everything is hooked up at breadboard!!

Amazing that it worked at all.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]