Modbus floating point conversion - arduino

I am using Arduino modbus library for measuring string current using hall sensor.Here library downloaded.Modbus library .I have sensor data in floating value & the library store the value in integer format.
question :
how can save the sensor value into integer format
How can assign user defined address. start address like 4000h instead of 0000H
code
#include <avr/wdt.h>
#include"glob.h"
//#define ID 1
void Device_ID_Reading()
{
for(row=0;row<9;row++)
{
digitalWrite(SO_enable,array1[row][0]);
digitalWrite(S1_enable,array1[row][1]);
digitalWrite(S2_enable,array1[row][2]);
Status_Out[row]=digitalRead(Read_IDstatus);
Device_ID =1*Status_Out[0]+2*Status_Out[1]+4*Status_Out[2]+8*Status_Out[3]+16*Status_Out[4]+32*Status_Out[5]+64*Status_Out[6]+128*Status_Out[7];
Serial.print("Device_ID");
Serial.print(row);
Serial.print(":\t");
Serial.println(Device_ID);
}
}
int8_t state = 0;
Modbus slave(Device_ID, 0, 0);
unsigned long tempus;
// data array for modbus network sharing
uint16_t au16data[30];
void Take_Reading()
{
for(row=0;row<9;row++)
{
// int k=(8*array[row][0]+4*array[row][1]+2*array[row][2]+1*array[row][3]);
// digitalWrite(Enablepin,array[row][0]);
digitalWrite(SO_enable,array1[row][1]);
digitalWrite(S1_enable,array1[row][2]);
digitalWrite(S2_enable,array1[row][3]);
//delay(100);
Sensor_Value0=analogRead(A0);
Sensor_Value1=analogRead(A5);
Mux1_array[row]=(Sensor_Value0 * ARDUINO_ANALOG_SCALING);
Mux2_array[row]=(Sensor_Value1 * ARDUINO_ANALOG_SCALING);
Current_Value1[row]= (Mux1_array[row]*35.1428571429)-87.6571428571;
Current_Value2[row]= (Mux2_array[row]*35.1428571429)-87.6571428571;
Current_Value3[row]=(Mux3_array[row]*35.1428571429)-87.6571428571;
}
}
void setup()
{
wdt_enable(WDTO_8S);
slave.begin( 9600 );
tempus = millis() + 100;
pinMode(3,OUTPUT);
pinMode(SO_enable, OUTPUT) ;// pin can enable/disable using digital IO 7 of arduino
pinMode(S1_enable, OUTPUT) ;// pin can enable/disable using digital IO 6 of arduino
pinMode(S2_enable, OUTPUT) ;// pin can enable/disable using digital IO 5 of arduino
// pinMode(Enablepin, OUTPUT) ;// pin can enable/disable using digital IO 4 of arduino
pinMode(A0, INPUT) ;
pinMode(A1, INPUT) ;
pinMode(A2,INPUT);
// Serial.begin(9600);
}
void loop()
{
digitalWrite(3,HIGH);
// wdt_reset();
Take_Reading();
Device_ID_Reading();
state = slave.poll( au16data,30 );
if (state > 4) {
tempus = millis() + 50;
digitalWrite(13, HIGH);
}
if (millis() > tempus) digitalWrite(13, LOW );
Modbus_call();
}
void Modbus_call()
{
/*reading of coil where i can succefully read value*/
au16data[1]=(int)(100*Current_Value1[0]);
au16data[2]=(int)(100*Current_Value1[1]);
au16data[3]=(int)(100*Current_Value1[3]);
au16data[4]=(int)(100*Current_Value1[4]);
au16data[5]=(int)(100*Current_Value1[5]);
au16data[6]=(int)(100*Current_Value1[6]);
au16data[7]=(int)(100*Current_Value1[7]);
au16data[8]=(int)(100*Current_Value1[8]);
au16data[9]=(int)(100*Current_Value2[0]);
au16data[10]=(int)(100*Current_Value2[1]);
au16data[11]=(int)(100*Current_Value2[2]);
au16data[12]=(int)(100*Current_Value2[3]);
au16data[16]=(int)(100*Current_Value2[4]);
au16data[17]=(int)(100*Current_Value2[5]);
au16data[18]=(int)(100*Current_Value2[6]);
au16data[19]=(int)(100*Current_Value2[7]);
uint16_t calcCRC( au16data[15]);
au16data[13] = slave.getInCnt();
au16data[14] = slave.getOutCnt();
au16data[15] = slave.getErrCnt();
}
Is there any other library where i can use the floating point directly.

Modbus as a protocol does not directly support floats. However you can put float data into adjacent registers. Use type punning to put the float data into your registers and pull it out on the other side.
union Pun {float f; uint32_t u;};
void encodeFloat(uint16_t *regs, float x)
{
union Pun pun;
pun.f = x;
regs[0] = (pun.u >> 16) & 0xFFFFU;
regs[1] = pun.u & 0xFFFFU;
}
float decodeFloat(const uint16_t *regs)
{
union Pun pun;
pun.u = ((uint32_t)regs[0] << 16) | regs[1];
return pun.f;
}
You would use it like so:
void Modbus_call()
{
/*reading of coil where i can succefully read value*/
encodeFloat(&au16data[ 0], Current_Value1[0]);
encodeFloat(&au16data[ 2], Current_Value1[1]);
encodeFloat(&au16data[ 4], Current_Value1[2]);
/* And so on... */
}

Related

Arduino send bad signal to interrupt pin

I have connected coin hopper and coin acceptor to one arduino uno, coin acceptor connected to pin 2, coin hopper to pin 3 - sensor and pin 7 - relay. When coin hopper switch relay, it is executing coininterrupt
for coin hopper I am using this script link
coin acceptor script: link
I need this 2 scripts working on 1 arduino
my code:
#define SENSOR 3
#define RELAY 7
#define ACCEPTOR 2
volatile boolean insert = false;
int pulse=0,count;
char sen;
int temp=0;
unsigned long int timer;
void setup()
{
Serial.begin(9600);
pinMode(SENSOR,INPUT_PULLUP);
pinMode(RELAY,OUTPUT);
sen=digitalRead(SENSOR);
digitalWrite(RELAY, HIGH);
attachInterrupt(digitalPinToInterrupt(ACCEPTOR), coinInterrupt, RISING);
}
void loop()
{
if (insert) {
insert = false;
Serial.println("coin");
delay(1000);
}
if(Serial.available())
{
timer=millis();
// temp is amount to dispense send to arduino
temp=Serial.parseInt();
if(temp>0){
digitalWrite(RELAY,LOW);}
}
sen=(sen<<1)|digitalRead(SENSOR);
// if hopper sensor read drop coin
if(sen==1)
{
timer=millis();
pulse++;
sen&=0x03;
Serial.println("out 1");
//if dispensed coins equal with coins to dispense stop engine
if(pulse==temp)
{
digitalWrite(RELAY,HIGH);
pulse=0;
temp=0;
}
}
// if amount dispensed is not equal with amount to dispense and engine running, stop
if((digitalRead(RELAY)==LOW)&(millis()-timer>2000))
{
digitalWrite(RELAY,HIGH);
pulse=0;
temp=0;
}
}
void coinInterrupt() {
insert = true;
}
I was trying to change pins (arduino uno support interrupts on pin 2 and 3 only) but problem still appears so I guess there is issue in the code
your sketch does not run in this state :
first fix errors :
declare insert as volatile
remove cpulse (not used anywhere)
change 'if()' to (I suppose) 'if (insert) ....'
remove stuff with 'sen' var : simply use if(digitalRead(SENSOR)) or if(!digitalRead(SENSOR))
except if you need to store relay state.
use logical operators like || or && unless you really need bitwise operations
example of result sketch :
#define SENSOR 3
#define RELAY 7
volatile boolean insert = false;
byte amountToDispense = 0;
int pulse = 0;
int temp = 0;
unsigned long int timer;
void setup()
{
Serial.begin(9600);
pinMode(SENSOR, INPUT_PULLUP);
pinMode(RELAY, OUTPUT);
digitalWrite(RELAY, HIGH);
attachInterrupt(digitalPinToInterrupt(2), coinInterrupt, RISING);
}
void loop()
{
if (insert ) {
insert = false;
Serial.println("coin");
delay(1000);
}
if (Serial.available())
{
timer = millis();
temp = Serial.parseInt();
if (temp > 0) {
//amountToDispense = Serial.read() - 48;
digitalWrite(RELAY, LOW);
}
}
if (digitalRead(SENSOR))
{
timer = millis();
pulse++;
Serial.println("out 1");
if (pulse >= temp)
{
digitalWrite(RELAY, HIGH);
pulse = 0;
temp = 0;
}
}
if (!digitalRead(RELAY) && (millis() - timer > 2000))
{
digitalWrite(RELAY, HIGH);
pulse = 0;
temp = 0;
}
}
void coinInterrupt() {
insert = true;
}
What is this supposed to do?
sen=(sen<<1)|digitalRead(SENSOR);
You init sen with digitalRead(SENSOR);
Assuming that pin is LOW when you start the sketch and turns HIGH, sen will become 1.
Next you do sen &= 0x03 so sen is still 1.
Again sen=(sen<<1)|digitalRead(SENSOR); , sen will either be 2 or 3.
Next loop run sen=(sen<<1)|digitalRead(SENSOR); sen is now 4 or 6. and so on...
I don't have time to think about what you want to achieve but this is definitely a problem as you'll only enter if (sen == 1) once and never again.
If this is not sufficient you should probably improve your post as it is unclear what arduino sends bad signal to interrup pin is supposed to mean. That doesn't make sense. Explain the expected behaviour of your program and how it behaves instead. add more comments so it becomes clear what you intend to do with each block of code so we don't have to interpret

Stroboscope with Arduino

first sorry for my bad english
I'm a student and I want to make a Stroboscope with Arduino for my school project
The frequency is variable between 10hz to 3000 hz and it changes using a rotary encoder
that when normally rotate the encoder 1 step frequency \pm 1hz and when rotate encoder when it pushed down frequency \pm 100hz
and Arduino make a PWM signal on pin 13 and it connect to a high power npn transistor and it turn on and off a 10 watt led
I code it using Encoder.h library by Paul Stoffregen and tone() function
but I have a PROBLEM
I code this program and upload it to Arduino Uno but it doesn't work IDK where is the problem
#include <Encoder.h>
#define ENCODER_PULSES_PER_STEP 1
int f = 10;
int direction;
Encoder myEnc(2, 3);
int t = 0;
void setup() {
pinMode(13, OUTPUT);
pinMode(4, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
direction = myEnc.read();
}
void loop() {
if (abs(direction) >= ENCODER_PULSES_PER_STEP) {
if (direction > 0) {
if (digitalRead(4) == 1) {
f++;
if (f >> 2500)f = 2500;
}
else {
f = f + 100;
if (f >> 2500)f = 2500;
}
} else {
if (digitalRead(4) == 1) {
f--;
if (f << 10)f = 10;
}
else {
f = f - 100;
}
}
myEnc.write(0);
}
tone(13, f);
}
When your program starts the function setup is executed once.
Then in an infinite loop the function loop is executed.
As you have direction = myEnc.read(); only in setup you'll only read the encoder once.
From the Encoder library's documentation:
/* Encoder Library - TwoKnobs Example
* http://www.pjrc.com/teensy/td_libs_Encoder.html
*
* This example code is in the public domain.
*/
#include <Encoder.h>
// Change these pin numbers to the pins connected to your encoder.
// Best Performance: both pins have interrupt capability
// Good Performance: only the first pin has interrupt capability
// Low Performance: neither pin has interrupt capability
Encoder knobLeft(5, 6);
Encoder knobRight(7, 8);
// avoid using pins with LEDs attached
void setup() {
Serial.begin(9600);
Serial.println("TwoKnobs Encoder Test:");
}
long positionLeft = -999;
long positionRight = -999;
void loop() {
long newLeft, newRight;
newLeft = knobLeft.read();
newRight = knobRight.read();
if (newLeft != positionLeft || newRight != positionRight) {
Serial.print("Left = ");
Serial.print(newLeft);
Serial.print(", Right = ");
Serial.print(newRight);
Serial.println();
positionLeft = newLeft;
positionRight = newRight;
}
// if a character is sent from the serial monitor,
// reset both back to zero.
if (Serial.available()) {
Serial.read();
Serial.println("Reset both knobs to zero");
knobLeft.write(0);
knobRight.write(0);
}
}
Notice the differences between your and their code.
Another more simple example from the GitHub repository to satisfy Juraj.
/* Encoder Library - Basic Example
* http://www.pjrc.com/teensy/td_libs_Encoder.html
*
* This example code is in the public domain.
*/
#include <Encoder.h>
// Change these two numbers to the pins connected to your encoder.
// Best Performance: both pins have interrupt capability
// Good Performance: only the first pin has interrupt capability
// Low Performance: neither pin has interrupt capability
Encoder myEnc(5, 6);
// avoid using pins with LEDs attached
void setup() {
Serial.begin(9600);
Serial.println("Basic Encoder Test:");
}
long oldPosition = -999;
void loop() {
long newPosition = myEnc.read();
if (newPosition != oldPosition) {
oldPosition = newPosition;
Serial.println(newPosition);
}
}
Also note that << is the binary left shift operator, not the less than operator < !
In if (f << 10)f = 10; you'll shift f 10 bits to the left. As this results in a number > 0, which is true, this condition will alway be met.
Same for >> which is the bitwise right shift operator, not greater then!

Can I temporarily disable Arduino Serial data receive?

I am working on a project and I encountered some problems.
I am using a DHT11 temperature sensor, an Arduino Uno and a TFT LCD display 2.2-inch model ITDB02-2.2.
What I want my project to do is to use 2 functioning modes for the sensor that I can select from the keyboard at the beginning of the program(one which is normal and one which will be used on special occasions)(so I need serial communication).
I noticed that the screen does not function if I start a serial communication at any rate so I used Arduino Serial.begin(9600) and Serial.end() for the mode selecting part of the program.
THE PROBLEM: My Arduino is still sending data through serial port even if I ended the serial communication and is looking like this:
I found out that Serial.end() function does not shut off serial communication but just the rate of communication. I am curious if you have any idea that I can use in order to get rid of the extra data, to neglect it before the computer receives it.
I`m stuck. I thought that interruptions would be a solution but they are not as far as I researched on the internet.
My ARDUINO CODE:
#include <SimpleDHT.h>
#include <UTFT.h>
UTFT myGLCD(ITDB22,A5,A4,A3,A2);
SimpleDHT11 dht11;
// Declare which fonts we will be using
extern uint8_t BigFont[];
//dht sensor data pin
int dataPinSensor1 = 12;
char mode;
int del;
void setup()
{
Serial.begin(9600);
Serial.print("Select functioning mode");
mode=SensorModeSelect(mode);
Serial.end();
pinMode(12, INPUT);
}
void loop()
{
if(mode=='1') {
FirstFuncMode(dataPinSensor1);
}
if(mode=='2') {
SecondFuncMode(dataPinSensor1,del);
}
delay(10);
}
char SensorModeSelect(char in)
{
char mode='0';
while(mode=='0') {
if(Serial.available() > 0) {
mode=Serial.read();
}
}
if (mode == '1') {
Serial.print("\nMOD1 SELECTED: press t key to aquire data \n");
}
if (mode == '2') {
Serial.print("\nMOD2 SELECTED: press q if you want to quit auto mode \n");
Serial.print("Select the data aquisition period(not smaller than 1 second) \n");
}
return mode;
}
int DataAqPeriod()
{
int del=0;
while(del==0) {
while(Serial.available() > 0) {
//Get char and convert to int
char a = Serial.read();
int c = a-48;
del *= 10;
del += c;
delay(10);
}
}
del*=1000;
return del;
}
void FirstFuncMode(int dataPinSensor1)
{
byte temperature = 0;
byte humidity = 0;
int err = SimpleDHTErrSuccess;
bool DispCond=false;
Serial.begin(9600);
delay(1500);
if (Serial.read() == 't' ) {
DispCond=true;
//read temperature and compare it with an error value
if((err = dht11.read(dataPinSensor1, &temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
Serial.print("unreliable measurement or unselected functioning mode");
}
byte f = temperature * 1.8 + 32;
Serial.print((int)temperature);
Serial.print(" *C, ");
Serial.print((int)f);
Serial.print(" *F, ");
Serial.print((int)humidity);
Serial.println(" H humidity");
delay(1500);
}
Serial.end();
if(DispCond==true) {
//Setup the LCD
myGLCD.InitLCD();
myGLCD.setFont(BigFont);
//print value on LCD
displayNoInit((int)temperature,(int)humidity);
}
}
void SecondFuncMode(int dataPinSensor1,int del)
{
bool q=false;
byte temperature = 0;
byte humidity = 0;
int err = SimpleDHTErrSuccess;
Serial.begin(9600);
del=DataAqPeriod();
Serial.end();
//Setup the LCD
myGLCD.InitLCD();
myGLCD.setFont(BigFont);
while(q==false) {
Serial.begin(9600);
//read temperature and compare it with an error value
if((err = dht11.read(dataPinSensor1, &temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
Serial.print("unreliable measurement or unselected functioning mode \n");
}
float f = temperature * 1.8 + 32;
Serial.print((int)temperature);
Serial.print(" *C, ");
Serial.print((int)f);
Serial.print(" *F, ");
Serial.print((int)humidity);
Serial.println(" H humidity");
delay(del);
if(Serial.read() == 'q')
q=true;
Serial.end();
displayNoInit((int)temperature,(int)humidity);
delay(10);
}
}
void displayNoInit(int temperature,int humidity)
{
//effective data display
myGLCD.clrScr();
myGLCD.setColor(255, 255, 0);
myGLCD.setBackColor(10,10,10);
myGLCD.print(" Temperature ", CENTER, 10);
myGLCD.setColor(254, 254, 254);
myGLCD.printNumI(temperature, CENTER, 45);
myGLCD.setColor(255, 255, 0);
myGLCD.print("C ", RIGHT, 45);
myGLCD.print("Relative Hum.", CENTER, 90);
myGLCD.setColor(204, 245, 250);
myGLCD.printNumI(humidity, CENTER, 120);
myGLCD.print("%", RIGHT, 120);
}
You are correct in the definition that Serial.end() does not disable the serial monitor, only the interrupts. After calling Serial.end() you can disable the serial monitor like so.
#include <avr/io.h>
// Save status register, disable interrupts
uint8_t oldSREG = SREG;
cli();
// Disable TX and RX
cbi(UCSRB, RXEN);
cbi(UCSRB, TXEN);
// Disable RX ISR
cbi(UCSRB, RXCIE);
// Flush the internal buffer
Serial.flush();
// Restore status register
SREG = oldSREG;

Trying to send a float value over SPI between 2 Arduinos

I am currently trying to send a float value across two Arduinos via SPI. Currently I am working to send a static value of 2.25 across and then read it via the Serial.println() command. I would then want to pass a float value from a linear displacement sensor. My end goal is to be able to have the master ask for information, the slave gathers the appropriate data and packages it and then master receives said data and does what it needs with it.
Currently I am getting an error "call of overloaded 'println(byte [7])' is ambiguous" and I am not to sure why I am getting this error. I am currently a mechanical engineering student and I am crash-coursing myself through C/C++. I am not entirely positive about what I am doing. I know that a float is 4 bytes and I am attempting to create a buffer of 7 bytes to store the float and the '\n' char with room to spare. My current code is below.
Master:
#include <SPI.h>
void setup() {
pinMode(SS,OUTPUT);
digitalWrite(SS,HIGH);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV4);
}
void loop() {
digitalWrite(SS,LOW);
float a = 2.25;
SPI.transfer(a);
SPI.transfer('\n');
digitalWrite(SS,HIGH);
}
My slave code is as follows:
#include <SPI.h>
byte buf[7];
volatile byte pos = 0;
volatile boolean process_it = false;
void setup() {
Serial.begin(9600);
pinMode(MISO,OUTPUT);
digitalWrite(MISO,LOW);
SPCR |= _BV(SPE); // SPI Enable, sets this Arduino to Slave
SPCR |= _BV(SPIE); // SPI interrupt enabled
}
ISR(SPI_STC_vect) {
// Interrupt Service Routine(SPI_(SPI Transfer Complete)_vector)
byte c = SPDR;
// SPDR = SPI Data Register, so you are saving the byte of information in that register to byte c
if (pos < sizeof buf) {
buf[pos++] = c;
if (c == '\n') {
process_it = true;
}
}
}
void loop() {
if (process_it = true) {
Serial.println(buf);
pos = 0;
process_it = false;
}
}
I figured out what I needed to do and I wanted to post my finished code. I also added an ability to transfer more than one float value.
Master:
#include <SPI.h>
float a = 3.14;
float b = 2.25;
uint8_t storage [12];
float buff[2] = {a, b};
void setup()
{
digitalWrite(SS, HIGH);
SPI.begin();
Serial.begin(9600);
SPI.setClockDivider(SPI_CLOCK_DIV8);
}
void loop()
{
digitalWrite(SS, LOW);
memcpy(storage, &buff, 8);
Serial.print("storage[0] = "); Serial.println(storage[0]); // the
following serial prints were to check i was getting the right decimal
numbers for the floats.
Serial.print("storage[1] = "); Serial.println(storage[1]);
Serial.print("storage[2] = "); Serial.println(storage[2]);
Serial.print("storage[3] = "); Serial.println(storage[3]);
Serial.print("storage[4] = "); Serial.println(storage[4]);
Serial.print("storage[5] = "); Serial.println(storage[5]);
Serial.print("storage[6] = "); Serial.println(storage[6]);
Serial.print("storage[7] = "); Serial.println(storage[7]);
SPI.transfer(storage, sizeof storage ); //SPI library allows a user to
transfer a whole array of bytes and you need to include the size of the
array.
digitalWrite(SS, HIGH);
delay(1000);
}
For my Slave code:
#include <SPI.h>
byte storage [8];
volatile byte pos;
volatile boolean process;
float buff[2];
void setup()
{
pinMode(MISO,OUTPUT);
SPCR |= _BV(SPE);
SPCR |= _BV(SPIE);
pos = 0;
process = false;
Serial.begin(9600);
}
ISR(SPI_STC_vect)
{
byte gathered = SPDR;
if( pos < sizeof storage)
{
storage[pos++] = gathered;
}
else
process = true;
}
void loop()
{
if( process )
{
Serial.print("storage[0] = "); Serial.println(storage[0]);
Serial.print("storage[1] = "); Serial.println(storage[1]);
Serial.print("storage[2] = "); Serial.println(storage[2]);
Serial.print("storage[3] = "); Serial.println(storage[3]);
Serial.print("storage[4] = "); Serial.println(storage[4]);
Serial.print("storage[5] = "); Serial.println(storage[5]);
Serial.print("storage[6] = "); Serial.println(storage[6]);
Serial.print("storage[7] = "); Serial.println(storage[7]);
memcpy(buff,&storage,8);
Serial.print("This is buff[0]");Serial.println(buff[0]);
Serial.print("This is buff[1]");Serial.println(buff[1]);
storage[pos] = 0;
pos = 0;
process = false;
}
}
The immediate problem is that Serial.print doesn't know what to do with a byte array. Either declare it as a char array or cast it in the print statement:
char buf[7];
OR
Serial.print((char*) buf);
Either way, though, it's not going to show up as a float like you want.
An easier way to do all this is to use memcpy or a union to go back and forth between float and bytes. On the master end:
uint8_t buf[4];
memcpy(buf, &a, 4);
Then use SPI to send 4 bytes. Reverse it on the peripheral end.
Note that sending '\n' as the termination byte is a bad idea because it can lead to weird behavior, since one of the bytes in the float could easily be 0x0a, the hexadecimal equivalent of '\n'.

Arduino SNES wireless receiver code questions

I am building a transmitter and receiver pair for two SNES controllers, as I don't like using long extension cords to get the controllers to reach the couch. I'm using ATmega328Ps for the AVRs, with RF24l01 wireless transceivers (using ManiacBugs RF24 library). I am using a modified snesPad library on the transmitter to poll the button states of two controllers and return them as a 32-bit unsigned long, then transmitting that to the receiver. All standard libraries, no issues there (so far).
However, on the receiver side, I have to properly respond to the latch and clock signals from the SNES, and I haven't found any stock libraries for that. For those not familiar with the SNES controllers, they are basically two 8-bit parallel to serial shift registers in series. They latch all of the button states on the rising edge of the latch signal (12 µs pulse high, normally low), drive the first bit on the falling edge of latch, and then drive each successive bit on the rising edge of clock (6 µs delay from fall of latch, normally high, 6 µs low - 6 µs high cycle).
I've decided to use an external interrupt to trigger the proper behavior for the latch pulse and each clock pulse. I'm new to programming Arduinos though, and new to C/C++ as well. Although my code will compile, I'm not certain if it will actually function as intended. If someone who has some experience with AVR's could take a look at my code and let me know if it will work, and if not, where and why, I would be very grateful!
Arduino sketch follows:
/*
Copyright (C) 2012 John Byers <jbyers2#wgu.edu>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 3 as published by the Free Software Foundation
*/
/**
* Dual Wireless Retro Controller Adapter Transmitter
*
* This is the reciever side code for the adapter set.
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <RF24_config.h>
//
// Hardware Configuration
//
RF24 radio(9,10);
//
// Variable Inits
//
volatile unsigned long state2 = 0xFFFFFFFF;
volatile byte i = 0;
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
int strobe = 2;
int clock = 3;
volatile int data1 = 5;
volatile int data2 = 6;
bool firstLoop = true;
volatile int status2 = 1;
void setup()
{
radio.begin();
radio.setRetries(0,15);
radio.enableDynamicPayloads();
Serial.begin(57600);
pinMode(strobe, INPUT);
pinMode(clock, INPUT);
pinMode(data1, OUTPUT); digitalWrite(data1, LOW);
pinMode(data2, OUTPUT); digitalWrite(data2, LOW);
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1,pipes[0]);
//
//Dump the configuration of the RF unit for debugging
//
radio.printDetails();
//
//Setup Interupts
//
attachInterrupt(strobe,latch,RISING);
attachInterrupt(clock,data,RISING);
}
void loop()
{
if (firstLoop) {
int status1 = 1;
bool ok = radio.write( &status1, sizeof(int));
firstLoop = false;
radio.startListening();
if (!ok) {
Serial.println("sync packet transmission failed");
}
else {
Serial.println("sync packet transmission successful");
}
}
if ( radio.available() )
{
unsigned long state = 0;
radio.read( &state, sizeof(unsigned long) );
Serial.println(state, BIN);
state2 = state;
}
else
{
Serial.println("No data recieved yet");
}
}
//Latch interrupt routine
void latch()
{
i = 0;
digitalWrite(data1,HIGH);
digitalWrite(data2,HIGH);
digitalWrite(data1,bitRead(state2,i));
digitalWrite(data2,bitRead(state2,(i+16)));
Serial.println("Bit0 out");
}
//Data interrupt routine
void data()
{
i++;
digitalWrite(data1,bitRead(state2,i));
digitalWrite(data2,bitRead(state2,(i+16)));
Serial.print("Bit");
Serial.print(i);
Serial.println(" out");
if(i=15)
{
digitalWrite(data1,LOW);
digitalWrite(data2,LOW);
radio.stopListening();
int status1 = status2;
bool ok = radio.write( &status1, sizeof(int));
if (!ok) {
Serial.println("sync packet transmission failed");
}
else {
Serial.println("sync packet transmission successful");
}
radio.startListening();
}
}

Resources