Is there any library available that can be used with avr like ATmega32, ATmega8 etc. like the Virtual Wire library (which can be used only with arduino).
I want to use it for transferring data through 433 Mhz tx and rx.
I like C.
-Thank You
Is there any library available that can be used with avr like ATmega32, ATmega8 etc. like the Virtual Wire library (which can be used only with arduino).
I want to use it for transferring data through 433 Mhz tx and rx.
I like C.
-Thank You
Depends on your C compiler but Fleury has excellent I2C/TWI library code for avr-gcc.
I2C/TWI is a two wire interface but I need one wire interface to use my RF 433 Mhz Tx and Rx
Are you sure (I very quickly looked at it : there were no obvious dependencies on Arduino's specificities) Virtula Wire is designed **only** for Arduini (and MSP430 arduino)can be used only with arduino?: there is a unique (700 lines, some -50%- being conditional) *.cpp file and a unique include file ) : maybe, for a given processor, you might port it..
Virtual Wire for radio is zero (except for testing) wires?
I2C/TWI is a two wire interface but I need one wire interface to use my RF 433 Mhz Tx and Rx
Just out of interest then, if it's really this you are talking about:
http://www.pjrc.com/teensy/td_li...
what stops you taking that source (or at least the algorithm) to a non-Arduino environment?
That will be a very big job for me, any other help will be appreciated. Anyway thanks clawson :-)
That will be a very big job for me
If the web page is correct, then there are 14 functions to port.
Not that much.
I can't see any C++-specific construct. Have you tried to feed the source file to your C compiler? Might be a pleasant surprise..
Yeah! I have tried that, it's not working because the DigitalWrite function is only for Arduino, I don,t know what else.
OK, I will try my best.
But the digitalWrite function interface is really trivial!
If you look at the innards of it in the Arduino sources, THAT is more complicated. But you do not need to bother with that.
I suppose you will have the VirtualWire code working on a specific port and pin in your app? If so, you "only" need to replace the calls to digitalWrite with standard C manipulation of the port/pin.
There are a total of seven (7) calls to digitalWrite in the VirtualWire source.
I'm not saying that this is done in 15 minutes. But if you take one problem at a time, look at ti, perhaps implement a small test-bench to try out individual problem solutions, dry-run them in the Simulator etc - then you will eventually get to a solution.
Climbing a mountain is done by taking one step after the other.
http://www.pjrc.com/teensy/td_li...
He based his code pretty heavily on the reference code available in an appendix of this PDF. Code is in assembler for AT89C2051, but this document is an important read in understanding the fundamentals. As @clawson said, the Arduino library is pretty well documented, but some concepts are left unexplained.
Funny to see this topic popping up now. I've just finished the first pass at an implementation of the same protocol from the ground up for use in an ATtiny85 project. Not ready for prime time yet, but it is working. It wasn't that difficult to do.
Honestly, the only things in your way are pinMode(), digitalRead(), digitalWrite(), and a timing function like millis(). The first three are dead easy. If you don't know about direct port manipulation via DDRn, PINn, and PORTn, there are plenty of tutorials. Timing isn't even required if you omit vw_wait_rx_max().
JJ
VirtualWire is made for Atmega85 also but I don't have one, I am using Atmega8 and Atmega32.
The three functions that you stated joeymorin is really easy, but I am a bit confused at the _timer_calc(speed, (uint8_t)-1, &nticks) function.
https://github.com/digistump/Dig...
this site is using it
https://github.com/m0/Updated-Ar...
but this is not.
Why is it? What it actually does?
Thank You
What it actually does?
// Common function for setting timer ticks @ prescaler values for speed
// Returns prescaler index into {0, 0, 3, 6, 8, 10, 12} array
// and sets nticks to compare-match value if lower than max_ticks
// returns 0 & nticks = 0 on fault
VirtualWire is made for Atmega85 also but I don't have one, I am using Atmega8 and Atmega32
And yes, recent versions of VirtualWire for Arduino support it, but that's not what I meant when I said I implemented it for the '85. I did not implement it for Arduino. I wrote my own implementation of the Virtual Wire protocol that was developed by RFM, and it can be used with any AVR. I just first used it on an '85. This is the same protocol on which Mike McCauley based his Arduino library.
I am a bit confused at the _timer_calc(speed, (uint8_t)-1, &nticks) function.https://github.com/digistump/Dig...
this site is using it
https://github.com/m0/Updated-Ar...
but this is not.
The second link is from version 1.4 which didn't have support for as many devices. The timing configuration is more straightforward and is done entirely within vw_setup().
The result is the same in each case, so examine the source at the second link, it's probably easier to understand.
Let's get rid of the conditional compilation statement, and look at the code just for the 168/328:
// Speed is in bits per sec RF rate void vw_setup(uint16_t speed) { // Calculate the OCR1A overflow count based on the required bit speed // and CPU clock rate uint16_t ocr1a = (F_CPU / 8UL) / speed; // Set up timer1 for a tick every 62.50 microseconds // for 2000 bits per sec TCCR1A = 0; TCCR1B = _BV(WGM12) | _BV(CS10); // Caution: special procedures for setting 16 bit regs OCR1A = ocr1a; // Enable interrupt TIMSK1 |= _BV(OCIE1A); // Set up digital IO pins pinMode(vw_tx_pin, OUTPUT); pinMode(vw_rx_pin, INPUT); pinMode(vw_ptt_pin, OUTPUT); digitalWrite(vw_ptt_pin, vw_ptt_inverted); }
Should be a lot easier to see the forest.
You can see that the timer is configured to roll over and trigger an interrupt at 8 times the baud rate. In version 1.14 and later, _timer_calc() is used to handle different devices that have 8-bit timers with different prescaler capabilities.
Since both devices you're trying to write for (the mega8 and mega32) have 16-bit timers, it might be better to just modify an earlier version like 1.4 to get what you need.
The author used to have links to all the previous versions. You can still get them, but you have to manually specify the link in your browser. Versions range from 1.0 through 1.20. Simply compose the correct link based on http://www.airspayce.com/mikem/a... where 'x' completes the version you're interested in.
A version history is available at the end of the main page.
JJ
I have modified the code to this but it is still not working it is compiling but it is not transmitting anything, I just connected an LED to the transmitting pin and never seen it blinking.
// VirtualWire.c // // Virtual Wire implementation for Arduino // See the README file in this directory fdor documentation // // Changes: // 2008-05-25: fixed a bug that could prevent messages with certain // bytes sequences being received (false message start detected) // // Author: Mike McCauley (mikem@open.com.au) // Copyright (C) 2008 Mike McCauley // $Id: VirtualWire.cpp,v 1.4 2009/03/31 20:49:41 mikem Exp mikem $ // Maximum number of bytes in a message, counting the byte count and FCS #define VW_MAX_MESSAGE_LEN 30 // The maximum payload length #define VW_MAX_PAYLOAD VW_MAX_MESSAGE_LEN-3 // The size of the receiver ramp. Ramp wraps modulu this number #define VW_RX_RAMP_LEN 160 // Number of samples per bit #define VW_RX_SAMPLES_PER_BIT 8 // Ramp adjustment parameters // Standard is if a transition occurs before VW_RAMP_TRANSITION (80) in the ramp, // the ramp is retarded by adding VW_RAMP_INC_RETARD (11) // else by adding VW_RAMP_INC_ADVANCE (29) // If there is no transition it is adjusted by VW_RAMP_INC (20) #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) // Outgoing message bits grouped as 6-bit words // 36 alternating 1/0 bits, followed by 12 bits of start symbol // Followed immediately by the 4-6 bit encoded byte count, // message buffer and 2 byte FCS // Each byte from the byte count on is translated into 2x6-bit words // Caution, each symbol is transmitted LSBit first, // but each byte is transmitted high nybble first #define VW_HEADER_LEN 8 #define INPUT 0 #define OUTPUT 1 #define true 1 #define false 0 static uint8_t vw_tx_buf[(VW_MAX_MESSAGE_LEN * 2) + VW_HEADER_LEN] = {0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x38, 0x2c}; // Number of symbols in vw_tx_buf to be sent; static uint8_t vw_tx_len = 0; // Index of the next symbol to send. Ranges from 0 to vw_tx_len static uint8_t vw_tx_index = 0; // Bit number of next bit to send static uint8_t vw_tx_bit = 0; // Sample number for the transmitter. Runs 0 to 7 during one bit interval static uint8_t vw_tx_sample = 0; // Flag to indicated the transmitter is active static volatile uint8_t vw_tx_enabled = 0; // Total number of messages sent static uint16_t vw_tx_msg_count = 0; // The digital IO pin number of the press to talk, enables the transmitter hardware static uint8_t vw_ptt_pin = 10; static uint8_t vw_ptt_inverted = 0; // The digital IO pin number of the receiver data static uint8_t vw_rx_pin = 11; // The digital IO pin number of the transmitter data static uint8_t vw_tx_pin = 12; // Current receiver sample static uint8_t vw_rx_sample = 0; // Last receiver sample static uint8_t vw_rx_last_sample = 0; // PLL ramp, varies between 0 and VW_RX_RAMP_LEN-1 (159) over // VW_RX_SAMPLES_PER_BIT (8) samples per nominal bit time. // When the PLL is synchronised, bit transitions happen at about the // 0 mark. static uint8_t vw_rx_pll_ramp = 0; // This is the integrate and dump integral. If there are <5 0 samples in the PLL cycle // the bit is declared a 0, else a 1 static uint8_t vw_rx_integrator = 0; // Flag indictate if we have seen the start symbol of a new message and are // in the processes of reading and decoding it static uint8_t vw_rx_active = 0; // Flag to indicate that a new message is available static volatile uint8_t vw_rx_done = 0; // Flag to indicate the receiver PLL is to run static uint8_t vw_rx_enabled = 0; // Last 12 bits received, so we can look for the start symbol static uint16_t vw_rx_bits = 0; // How many bits of message we have received. Ranges from 0 to 12 static uint8_t vw_rx_bit_count = 0; // The incoming message buffer static uint8_t vw_rx_buf[VW_MAX_MESSAGE_LEN]; // The incoming message expected length static uint8_t vw_rx_count = 0; // The incoming message buffer length received so far static volatile uint8_t vw_rx_len = 0; // Number of bad messages received and dropped due to bad lengths static uint8_t vw_rx_bad = 0; // Number of good messages received static uint8_t vw_rx_good = 0; void pinMode(int pin, int status) { if (pin == 11) { DDRD |= 0<<2; //PORTD |= 1<<2; } if (pin == 12) { DDRB |= 1<<1; PORTB |= 1<<1; } else; } void digitalWrite(int pin, int status) { if (pin == 11 && status == 1) { PORTD = 1<<2; } if (pin == 11 && status == 0) { PORTD = 0<<2; } if (pin == 12 && status == 1) { PORTB |= 1<<1; } if (pin == 12 && status == 0) { PORTB |= 0<<1; } else; } int digitalRead(int pin) { if (pin == 11) { if(bit_is_set(PORTD,2)) return 1; if(bit_is_clear(PORTD,2)) return 0; } if (pin == 12) { if(bit_is_set(PORTB,1)) return 1; if(bit_is_clear(PORTB,1)) return 0; } else return -2; } // 4 bit to 6 bit symbol converter table // Used to convert the high and low nybbles of the transmitted data // into 6 bit symbols for transmission. Each 6-bit symbol has 3 1s and 3 0s // with at most 2 consecutive identical bits static uint8_t symbols[] = { 0xd, 0xe, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c, 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x32, 0x34 }; // Compute CRC over count bytes. // This should only be ever called at user level, not interrupt level 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; } // Convert a 6 bit encoded symbol into its 4 bit decoded equivalent 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 } // Set the output pin number for transmitter data void vw_set_tx_pin(uint8_t pin) { vw_tx_pin = pin; } // Set the pin number for input receiver data void vw_set_rx_pin(uint8_t pin) { vw_rx_pin = pin; } // Set the output pin number for transmitter PTT enable void vw_set_ptt_pin(uint8_t pin) { vw_ptt_pin = pin; } // Set the ptt pin inverted (low to transmit) void vw_set_ptt_inverted(uint8_t inverted) { vw_ptt_inverted = inverted; } // Called 8 times per bit period // Phase locked loop tries to synchronise with the transmitter so that bit // transitions occur at about the time vw_rx_pll_ramp is 0; // Then the average is computed over each bit period to deduce the bit value 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 } } } // Speed is in bits per sec RF rate void vw_setup(uint16_t speed) { // Calculate the OCR1A overflow count based on the required bit speed // and CPU clock rate uint16_t ocr1a = (F_CPU / 8UL) / speed; //#ifndef TEST // Set up timer1 for a tick every 62.50 microseconds // for 2000 bits per sec TCCR1A = 0; TCCR1B = _BV(WGM12) | _BV(CS10); // Caution: special procedures for setting 16 bit regs OCR1A = ocr1a; // Enable interrupt //#ifdef TIMSK1 // atmega168 //TIMSK1 |= _BV(OCIE1A); //#else // others TIMSK |= _BV(OCIE1A); //#endif // Set up digital IO pins pinMode(vw_tx_pin, OUTPUT); pinMode(vw_rx_pin, INPUT); pinMode(vw_ptt_pin, OUTPUT); digitalWrite(vw_ptt_pin, vw_ptt_inverted); } // Start the transmitter, call when the tx buffer is ready to go and vw_tx_len is // set to the total number of symbols to send void vw_tx_start() { vw_tx_index = 0; vw_tx_bit = 0; vw_tx_sample = 0; // Disable the receiver PLL vw_rx_enabled = false; // Enable the transmitter hardware digitalWrite(vw_ptt_pin, true ^ vw_ptt_inverted); // Next tick interrupt will send the first bit vw_tx_enabled = true; } // Stop the transmitter, call when all bits are sent void vw_tx_stop() { // Disable the transmitter hardware digitalWrite(vw_ptt_pin, false ^ vw_ptt_inverted); digitalWrite(vw_tx_pin, false); // No more ticks for the transmitter vw_tx_enabled = false; // Enable the receiver PLL vw_rx_enabled = true; } // Enable the receiver. When a message becomes available, vw_rx_done flag // is set, and vw_wait_rx() will return. void vw_rx_start() { if (!vw_rx_enabled) { vw_rx_enabled = true; vw_rx_active = false; // Never restart a partial message } } // Disable the receiver void vw_rx_stop() { vw_rx_enabled = false; } // Return true if the transmitter is active uint8_t vx_tx_active() { return vw_tx_enabled; } // Wait for the transmitter to become available // Busy-wait loop until the ISR says the message has been sent void vw_wait_tx() { while (vw_tx_enabled) ; } // Wait for the receiver to get a message // Busy-wait loop until the ISR says a message is available // can then call vw_get_message() void vw_wait_rx() { while (!vw_rx_done) ; } // Wait at most max milliseconds for the receiver to receive a message // Return the truth of whether there is a message uint8_t vw_wait_rx_max(unsigned long milliseconds) { unsigned long start = millis(); while (!vw_rx_done && ((millis() - start) < milliseconds)) ; return vw_rx_done; } // Wait until transmitter is available and encode and queue the message // into vw_tx_buf // The message is raw bytes, with no packet structure imposed // It is transmitted preceded a byte count and followed by 2 FCS bytes 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; } // This is the interrupt service routine called when timer1 overflows // Its job is to output the next bit from the transmitter (every 8 calls) // and to call the PLL code if the receiver is enabled //ISR(SIG_OUTPUT_COMPARE1A) //SIGNAL(TIMER1_COMPA_vect) ISR(TIMER1_COMPA_vect) { vw_rx_sample = digitalRead(vw_rx_pin); // Do transmitter stuff first to reduce transmitter bit jitter due // to variable receiver processing 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_bit >= 6) { vw_tx_bit = 0; vw_tx_index++; } } } if (vw_tx_sample > 7) vw_tx_sample = 0; if (vw_rx_enabled) vw_pll(); } // Return true if there is a message available uint8_t vw_have_message() { return vw_rx_done; } // Get the last message received (without byte count or FCS) // Copy at most *len bytes, set *len to the actual number copied // Return true if there is a message and the FCS is OK 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? }
and this is the header file
// VirtualWire.h // // Virtual Wire implementation for Arduino // See the README file in this directory fdor documentation // // Author: Mike McCauley (mikem@open.com.au) // Copyright (C) 2008 Mike McCauley // $Id: VirtualWire.h,v 1.3 2009/03/30 00:07:24 mikem Exp $ #include#include #include #include "VirtualWire.c" /*#if ARDUINO < 100 #include #else #include #endif*/ // These defs cause trouble on some versions of Arduino #undef abs #undef double #undef round // Cant really do this as a real C++ class, since we need to have // an ISR // Set the digital IO pin to be for transmit data // Defaults to 12 void vw_set_tx_pin(uint8_t pin); // Set the digital IO pin to be for receive data // Defaults to 11 void vw_set_rx_pin(uint8_t pin); // Set the digital IO pin to enable the transmitter (press to talk) // Defaults to 10 void vw_set_ptt_pin(uint8_t pin); // By default the PTT pin goes high when the transmitter is enabled. // This flag forces it low when the transmitter is enabled. void vw_set_ptt_inverted(uint8_t inverted); // Initialise the VirtualWire software, to operate at speed bits per second // Call this one in your setup() after any vw_set_* calls // Must call vw_rx_start() before you will get any messages void vw_setup(uint16_t speed); // Start the Phase Locked Loop listening to the receiver // Must do this before you can receive any messages // When a message is available (good checksum or not), vw_have_message(); // will return true. void vw_rx_start(); // Stop the Phase Locked Loop listening to the receiver // No messages will be received until vw_rx_start() is called again // Saves interrupt processing cycles void vw_rx_stop(); // Return true if the transmitter is active uint8_t vx_tx_active(); // Block until the transmitter is idle void vw_wait_tx(); // Block until a message is available void vw_wait_rx(); // or for a max time uint8_t vw_wait_rx_max(unsigned long milliseconds); // Send a message with the given length. Returns almost immediately, // and message will be sent at the right timing by interrupts // Returns true if the message was accepted for transmissions // Returns false if the message is too long (>VW_MAX_MESSAGE_LEN - 3) uint8_t vw_send(uint8_t* buf, uint8_t len); // Returns true if an unread message is available uint8_t vw_have_message(); // If a message is available (good checksum or not), copies // up to *len octets to buf. // Returns true if there was a message and the checksum was good uint8_t vw_get_message(uint8_t* buf, uint8_t* len);
These:
DDRD |= 0<<2; . . . PORTD = 0<<2; . . . PORTB |= 0<<1;
... do nothing. Shifting 0 by any amount is still zero.
Your implementation of pinMode() and friends won't work. It looks like you're just implementing them for the default VirtualWire RX and TX pins, and mapping them to your own choices for ports/pins, which I assume are PD2 for RX and PB1 for TX...? This is going to be hard to maintain. Why not look at the Arduino source? Start with wiring_digital.c.
For this very specific case, this should work:
void pinMode(int pin, int mode) { switch (pin) { case 11: if (mode) { DDRD |= (1<<PD2); } else { DDRD &= ~(1<<PD2); } break; case 12: if (mode) { DDRB |= (1<<PB1); } else { DDRB &= ~(1<<PB1); } break; } } void digitalWrite(int pin, int level) { switch (pin) { case 11: if (level) { PORTD = (1<<PD2); } else { PORTD = ~(1<<PD2); } break; case 12: if (level) { PORTB = (1<<PB1); } else { PORTB = ~(1<<PB1); } break; } } int digitalRead(int pin) { switch (pin) { case 11: return !!(PIND & (1<<PD2)); break; case 12: return !!(PINB & (1<<PB1)); break; } }
Untested, and bear in mind that this is not a general-purpose solution.
Arduino have come up with their own routines to map their pin numbering onto the ports and bits of the AVR. There is no need for you to adhere to that. I sometimes use macros similar to these:
// Required by macros below #define concatenate(a, b) __concatenate(a, b) #define __concatenate(a, b) a ## b // Similar to Arduino's digitalWrite() function #define write_port(port, bit, val) \ do { if (val) { concatenate(PORT, port) |= (1<<bit); } \ else { concatenate(PORT, port) &= ~(1<<bit); } } while(0) // Similar to Arduino's pinMode() function #define write_ddr(port, bit, val) \ do { if (val) { concatenate(DDR, port) |= (1<<bit); } \ else { concatenate(DDR, port) &= ~(1<<bit); } } while(0) // Similar to Arduino's digitalRead() function #define read_pin(port, bit) !!(concatenate(PIN, port) & (1<<bit))
You use them like this:
// Set PD2 as an input write_ddr(D, 2, 0); // Set PB1 as an output write_ddr(B, 1, 1); // Read input PD2 and place it into variable foo foo = read_pin(D, 2); // Write 0 to output pin PB2 write_port(B, 2, 0);
These macros also let me define my own macros for pins:
#define LED_PORT D #define LED_BIT 0 #define BUTTON_PORT B #define BUTTON_BIT 5 write_ddr(LED_PORT, LED_BIT, 1) write_ddr(BUTTON_PORT, BUTTON_BIT, 0); while (1) { write(LED_PORT, LED_BIT, read_pin(BUTTON_PORT, BUTTON_BIT)); }
Other members have written their own, widely used macros.
You seem to be missing some of the fundamentals. Notably, proper bit manipulation, and how to access the general purpose I/O pins via DDRn, PORTn, and PINn. Have a look at the tutorials section, there are lots of resources there, including some of the macros used by other members.
JJ
///////////////////////////////////////////////////////////////////////////////
[captcha] CAPTCHA'D!! :evil: [/captcha]
Still the same problem compiling but not working/transmitting.
I have a strong feeling that it is never entering the interrupt.
Please someone solve this.
I firstly want to do it on a single pin then want generalize it.
Still the same problem compiling but not working/transmitting.
I have a strong feeling that it is never entering the interrupt.
Please someone solve this.
You've only posted your (slightly) modified library. You haven't posted your own code that uses it. How are we supposed to guess what's going wrong?
As a stab in the dark, I'd guess you haven't enabled global interrupts. Arduino does that for you, but you have to do it yourself with plain C/C++. Have you done so? If not, add:
#include
... at the top of your source, and this after calling vw_setup():
sei();
If it still doesn't work, post a minimal program that exhibits the problem, and explain what you've done to try to solve that problem.
[edit]
#include
... in the library, either. Without it, the ISR may generate compile-time warnings, but won't otherwise be properly hooked into the vector table. Again, Arduino normally does this for you via:
#include
JJ
Why the [phneep!] am I getting captcha'd!?
Ok, Here's my code.
#define F_CPU 16000000UL #include#include #include #include "VirtualWire.h" int main(void) { const char *msg = "hello"; sei(); vw_setup(2000); while(1) { vw_send((uint8_t *)msg, strlen(msg)); vw_wait_tx(); // Wait until the whole message is gone _delay_ms(200); } }
What is the use of _crc_ccitt_update() in C.
What is the use of _crc_ccitt_update() in C.
Anyway, tell us what you miss or do not understand in the following documentation: http://www.nongnu.org/avr-libc/u... . (That was the first hit when I Googled "_crc_ccitt_update()". And if you have the avr-gcc/avrlibc tool chain installed on your computer then chances are good that you also have the avrlibc documentation installed locally.)
Before you ask: http://en.wikipedia.org/wiki/Cyc...
OK, then it is redundancy check. I am struck in the code that your first link uses.
I just want to know , if i call
data = _crc_ccitt_update(0xff00,0xff); data2 = _crc_ccitt_update(0xffff,0xff);
what will be the value of data and data2
Ok, Here's my code.#define F_CPU 16000000UL #include#include #include #include "VirtualWire.h" int main(void) { const char *msg = "hello"; sei(); vw_setup(2000); while(1) { vw_send((uint8_t *)msg, strlen(msg)); vw_wait_tx(); // Wait until the whole message is gone _delay_ms(200); } }
Did you add:
#include
... to VirtualWire.c like I suggested?
JJ
OK, then it is redundancy check. I am struck in the code that your first link uses.
I just want to know , if i calldata = _crc_ccitt_update(0xff00,0xff); data2 = _crc_ccitt_update(0xffff,0xff);what will be the value of data and data2
This is not relevant to your problem. If you're not seeing activity on the TX pin, you have deeper problems.
JJ
I just want to know , if i call
Code:
data = _crc_ccitt_update(0xff00,0xff);
data2 = _crc_ccitt_update(0xffff,0xff);what will be the value of data and data2
Ok, I surrendered but came up with my own version. I have prepared only the sender's protocol. But it is having problems, like it is sending correctly the bits first time, by the second round it is not transmitting anything it's just saying high.
Here is my code:
/* * RF_Sender.c * * Created: 10/4/2013 2:45:23 AM * Author: Jem */ #define F_CPU 16000000UL #include#include #include int ow_ocr1a; uint8_t ow_tccr1b,tccr1b; void ow_Setup(int); void ow_RegisterEnable(void); void ow_RegisterDisable(void); void ow_Send(char); void ow_Reset(void); void ow_CreatePacket(uint8_t); void ow_BitSelector(void); void ow_Setup(int speed) { sei(); ow_tccr1b = 0b00001111; ow_ocr1a = (int) F_CPU / speed; } void ow_RegisterEnable() { tccr1b = TCCR1B; TCCR1B = ow_tccr1b; TIMSK |= 1<<OCIE1A; OCR1A = ow_ocr1a; } void ow_RegisterDisable() { TCCR1B = tccr1b; TIMSK = 0x00; } int packet[44] = {1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0}; int ow_NextBit = 0; int ow_BitWritten = 0; int ow_Busy = 0; int selection = 0; void ow_Send(char data) { uint8_t data_to_send; data_to_send = (uint8_t) data; ow_Busy = 1; ow_CreatePacket(data_to_send); } void ow_Reset() { ow_NextBit = 0; ow_BitWritten = 0; ow_Busy = 0; selection = 0; } int ow_PacketReadyFlag = 0; void ow_CreatePacket(uint8_t data) { int index = 24; int i; /*for (i=0;i<8;i++) { if (bit_is_set(data,i)) { packet = 1; packet[index+1] = 0; } else { packet
= 0; packet[index+1] = 1; } index += 2; }*/ ow_BitSelector(); ow_PacketReadyFlag = 1; ow_RegisterEnable(); } void ow_BitSelector() { if (selection < 43) { if (ow_BitWritten) { selection++; ow_NextBit = packet[selection]; } else { ow_NextBit = packet[selection]; } } else { ow_PacketReadyFlag = 0; //ow_RegisterDisable(); ow_Reset(); } ow_BitWritten = 0; } ISR(TIMER1_COMPA_vect) { if (ow_PacketReadyFlag) { PORTB = ow_NextBit<<1; ow_BitWritten = 1; ow_BitSelector(); } TCNT1 = 0; } int main(void) { DDRB |= 1<<1; PORTB |= 0<<1; ow_Setup(3000); while(1) { if (ow_Busy == 0) { ow_Send(0b11111111); } //_delay_ms(200); } }
Just ignore some of the commented out codes and some illogical steps, i am using this for only test purposes, running it on a super slow mode so that i could visualize the square wave through an led. It is just sending the bits in the array packet. But the problem stays.
-Please help I need this.
You have:
PORTB |= 0<<1;
You probably mean:
PORTB &= ~(1<<1);
You have:
ow_ocr1a = (int) F_CPU / speed;
This casts F_CPU, which is an unsigned long, as a signed 16-bit int. With F_CPU defined as 16000000, this leaves a value of (16000000 % 65536), which is 9,216, which is then divided by speed. What you probably meant was:
ow_ocr1a = (int)(F_CPU / speed);
... but since ow_ocr1a is already a 16-bit int, there is no need to do the cast at all.
Also, you should make ow_ocr1a unsigned.
None of that should 'break' your code in the way you've described.
However, this:
ow_tccr1b = 0b00001111;
Sets TIMER1 to clock on an external pin T1, which happens to be PB1. So the very pin you are wiggling for TX is the same pin that clocks the timer. Surely this isn't what you meant.
I'd guess you meant to select the highest prescaler available (so you can see your LED) which is 1024, but which is selected with CS1[2:0] = 0b101, so:
ow_tccr1b = 0b00001101;
BTW, please don't use magic numbers like this. It forces us to look at a datasheet to help you. Instead:
ow_tccr1b = (1<<WGM12) | (1<<CS12) | (1<<CS10);
... is much more informative.
Just ignore some of the commented out codes and some illogical steps, i am using this for only test purposes, running it on a super slow mode so that i could visualize the square wave through an led. It is just sending the bits in the array packet. But the problem stays.
I strongly suggest you return to VW and address the issues you are having one by one. Post specific questions here. Break the problem down into smaller parts. Understand timers by going through the many timer tutorials available on this site. Ditto for interrupts. Ditto for bit manipulation. Ditto for port I/O.
JJ
[edit]code typo[/edit]
Just ignore some of the commented out codes and some illogical steps
Remember:
1) The quality of the answers you get is highly correlated with the quality of the question you ask, and
2) You are in a competition for attention and help - The more you put into your questions the more attention you get.
As you told joeymorin, I followed your step, just reviewd your previous posts and added the interrrupt header file to VirtualWire h and c file, and it is working fine now.
A million thanks for all your help.
I just love this forum.
I will make it available on github soon with a clean code.
... it is working fine now.
I will make it available on github soon with a clean code.
JJ
Could someone please tell me where I can find the github with the virtual wire substitute code? I know this post is old but I'm curios to have a look at it and it doesn't seem to be available on the Virtualwire google group either.
Thanks in advance,
OK, case reopened, I want to make this user friendly. For now the functions like vw_set_rx_pin(), vw_set_tx_pin will not work.
I want to make it work, I want to make the output and input pins changeable.
So I made this adjustments, but they aren't working.
void pinMode(unsigned char port, unsigned char pin, int mode) { unsigned char ddr; if(port == PORTA) { ddr = DDRA; } if (port == PORTB) { ddr = DDRB; } if (port == PORTC) { ddr = DDRC; } if (port == PORTD) { ddr = DDRD; } if (mode) { ddr |= (1<<pin); } else { ddr &= ~(1<<pin); } } void digitalWrite(unsigned char port, unsigned char pin, int level) { if (level) { port = (1<<pin); } else { port = ~(1<<pin); } } int digitalRead(unsigned char port, unsigned char pin) { unsigned char pinn; if(port == PORTA) { pinn = PINA; } if (port == PORTB) { pinn = PINB; } if (port == PORTC) { pinn = PINC; } if (port == PORTD) { pinn = PIND; } if (bit_is_set(pinn,pin)) { return 1; } else if(bit_is_clear(pinn,pin)) { return 0; } }
and this
void vw_set_tx_pin(unsigned char port, unsigned char pin) { vw_tx_port = port; vw_tx_pin = pin; } // Set the pin number for input receiver data void vw_set_rx_pin(unsigned char port, unsigned char pin) { vw_rx_port = port; vw_rx_pin = pin; }
and this also
pinMode(vw_tx_port,vw_tx_pin, OUTPUT); pinMode(vw_rx_port,vw_rx_pin, INPUT); pinMode(vw_ptt_port,vw_ptt_pin, OUTPUT); digitalWrite(vw_ptt_port,vw_ptt_pin, vw_ptt_inverted);
and everywhere else where those funtions were present.
but they aren't working.
It is not transmitting anything. I have connected and led for testing purposes, it is not lighting up in any direction.
Of course your code wont work as you expect. PORTA etc are a little special. You want to get the address of it. Considering what you are wanting to do has been discussed and solved many times before, i surprised you haven't done a search to find the answer.
https://www.avrfreaks.net/index.p...
Was top of the list. This should enlighten you.
When you write simple, but critical functions, write some test code for them rather than hope they work and try them as part of a complex application. With the test code you can run it in the simulator and figure out very quickly if it works or not.
SORRY GUYS, since I am reading on lots of sites to get rid of my problem, I forgot this is an english-based Forum.
Please ignore this post except the attached files.
English text is one post below. (please help nevertheless :-P)
Hallo Leute,
ich würde diesen Thread gerne wieder aufleben lassen, da meine Frage wohl am ehesten hier rein passt.
Ich habe meine 4 Dateien "Main.c", "VirtualWire.cpp", "VirtualWire_Config.h" sowie "VirtualWire.h" angehängt.
Ich möchte die Virtual Wire LIB auf dem Attiny2313A benutzen. (Quelle: http://www.airspayce.com/mikem/a... )
Da ich keine C++ Kenntnisse habe, habe ich bewusst Virtual Wire und nicht Radiohead gewählt.
Bisher versuche ich in meinem Programm nur ein paar Zeichen zu Senden.
Zu Testzwecken habe ich eine LED am Sendepin angeschlossen, sowie eine LED am PTT-Pin.
Ich nutze Atmelstudio 7, mit standard Einstellungen:
Optimization steht auf -O1
Mein Code compiliert erfolgreich ohne Errors, jedoch passiert nicht was passieren soll:
Die Delay-Funktion macht deutlich größere Delays, als sie soll.
Ich habe das ganze bereits eingrenzen können:
Die Delays werden größer/unpassend, da in der VirtualWire.cpp in Zeile 121 in der Funktion "timerSetup" ein Prescaler gesetzt wird.
Dieser wird für die passende Bitrate der Sendenfunktion berechnet und in "vw_setup" aufgerufen.
"vw_setup()" wird in der main-funktion aufgerufen.
Kommentiere ich die Zeile in der die "timerSetup"-Funktion aufgerufen wirdaus, tut meine blink-Funktion, was sie soll, diese nutze ich um zu testen ob die _delay_ms() richtig funktioniert.
Mein Attiny läuft mit dem internen 8Mhz Oszillator und gesetztem Prescalerwert 8 (standard-shipping einstellungen, keine verändertren Fusebits), daher schreibe ich die cpu-define auf 1Mhz.
Da sich auch die VirtualWire-lib der "delay" Funktion bedient, gehe ich davon aus, dass das Setzen eines Prescalers und damit die Beeinträchtigung des CPU-Clocks berücksichtig sein sollte ?!
An diesem Punkt setzt meine Frage an: Hat jemand mit dieser LIB inzwischen bereits erfolgreich gearbeitet, OHNE die Arduino IDE zu benutzen oder erkennt jemand, wo hier der Fehler liegen könnte ?
Würde mich über Hilfe riesig freuen, da ich bereits seit knapp 2 Wochen rumprobiere und langsam frustriert werde.
Einen schönen 2. Adventsabend wünsche ich!
Sry guys, forgot to speak english!
So I tried to ask the following:
I'd like to let this thread revive, since my question fits the best in this thread:
I attached my 4 files: "Main.c", "VirtualWire.cpp", "VirtualWire_Config.h" aswell as "VirtualWire.h".
I'd like to use the virtualWire lib on my Attiny2313A. (From this source: http://www.airspayce.com/mikem/a...)
Because I have no sound knowledge to "c++" I chose virtualWire instead of RadioHead.
At the moment I am just trying to send some characters in my program.
For testing purposes I connected a led to the sending pin as well as to the PTT-pin.
I am using Atmel Studio 7 as IDE with the default settings:
Optimization is on "-O1".
My code compiles without any error but my program does not work.
The delay-function for example becomes way too "slow".
It is because a prescaler for the clk gets set in Line 121 in the "VirtualWire.cpp" file in the called "timerSetup" function.
This prescaler is calculated for the fitting Bit-Rate of the sending function.
the timerSetup is called in the vw_setup(). The vw_setup is called in my main-function.
The attiny runs with the shipped settings: intern 8MHZ oscillator and activated prescaler 8. So I wrote the cpu-define to 1Mhz (1000000UL).
I thought, that since the virtualWire lib uses the delay function aswell, the functions within the virtualWire lib would not affect the practicality of the delay function, but it does...
So my question is: Does anybody see where my fault is or did anybody use it with another AVR than the tiny45?
Is it allowed to include a *.cpp file to a c-Project ?
Would be very great, if anybody could help me out, I am searching the internet and the code since nearly two weeks and it is frustrating me..
Thank you very much!