SOLVED:Mirf Library and sending Pot values AND buttonpresses

Hi folks. :slight_smile:
I am in the process of designing a wireless MIDI device sending analog sensor info and keypresses for noteon/noteoffs. I am using the Mirf library. The boards | am using are:
1x duemilanove (reciever) and
1xMega2560 (TRANSMITTER)
I am using the cheap black nrf24l01s from China :slight_smile:

I have had success sending pot information from the TX to the RX. The codes are below:

// Steve's NRF24l01 sketch sending pot values in an array
// From a Mega2560 to an Arduino Duemilanove.
// This is the Tx end.
#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
int timer = 100; // The higher the number, the slower the timing.
int potpins[] = {
A0, A1, A2, A3}; // an array of pin numbers to which LEDs are attached
int pinCount = 4; // the number of pins (i.e. the length of the array)

int pots;

void setup(){

Serial.begin(9600);
int thisPin;

Mirf.cePin = 48; //ce pin on Mega 2560
Mirf.csnPin = 49; //csn pin on Mega 2560
Mirf.spi = &MirfHardwareSpi;
Mirf.init();
Mirf.setRADDR((byte *)"clie1");
Mirf.payload =sizeof(pots);
Mirf.config();
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
pinMode(potpins[thisPin], INPUT);
}
}

void loop(){ // loop from the lowest pin to the highest:
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
// turn the pin on:
int pots=analogRead(potpins[thisPin]);
delay(timer);
// turn the pin off:
//digitalWrite(ledPins[thisPin], LOW);

Mirf.setTADDR((byte *)"serv1");

Mirf.send((byte *) &pots);

// Mirf.send((byte *) &butstate);

while(Mirf.isSending()){
}
}
}

Reciever:

// Steve's NRF24l01 using the Mirf Library. Recieving end of
// Pots on Mega2560.
// Serial monitor displays the values of the pots.

#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>

int pots;

void setup(){

Serial.begin(9600);
//pinMode(led,OUTPUT);
Mirf.spi = &MirfHardwareSpi;
Mirf.init();
Mirf.setRADDR((byte *)"serv1");
Mirf.payload =sizeof(pots);

Mirf.config();
}

void loop(){

while(!Mirf.dataReady()){
}
Mirf.getData((byte *) &pots);
// delay(10);
//Mirf.getData((byte *) &butstate);
// digitalWrite(led,butstate);

//Serial.println(rate);
//Serial.println (siz);
Serial.println(pots);
delay(10);
}

The serial port reads the sensor info nicely ( I am using 3 pots and one LDR.)

Now I want to send a button press but I am stumped as to how to send the information across wirelessly.

Can anyone help me with this?

I don't know how to set the payload so it accepts more than one array and is it possible to use Mirf.send commands one after the other?
I have tried setting up a button on a digital pin and sending the pin information as a variable set to read digitalRead(buttonpin) but on the RX end I get a stream of noughts followed by a few other numbers. These are not related to me pressing the button...

If anyone could help me to send button presses I would be really grateful. :slight_smile:

These modules are really quite good for sending simple info and you have a 32 byte max which is more than enough....

Thanks and kind regards,
Steve.

The analogRead() output is a value in the range 0 to 1023.
The digitalRead() output is a value in the range 0 to 1.

Sending switch data is EXACTLY like sending potentiometer data.

Hi and thanks but...

How would I set the payload to accept both types of data?
When I have tried this:
Mirf.payload=sizeof(pots+keypresses);
The reciever doesn't output 0s and 1s . The data it outputs isn't relative to the button presses..

I am sending the button presses straight after sending the pot values..

When I have tried this:
Mirf.payload=sizeof(pots+keypresses);
The reciever doesn't output 0s and 1s . The data it outputs isn't relative to the button presses..

First, pots is a lousy name for a variable that holds one value. What, exactly, is pots+keypresses? It is an int. So, you are not doubling the size of the payload. You are, in fact, not changing the size of the payload at all. All you are doing is assigning the same value AS THE PAYLOAD, which hardly seems like the correct thing to be doing.

You need to look at the documentation for the library, and see how to set the payload size.

But, since you are sending a new payload for every potentiometer reading, I don't see that changing the size of the payload is really going to matter. Unless, you formulate the payload correctly.

Hiya.
Thanks for the input. I see what you mean. I'll have a look at the library.
Also I realize that no matter what is coming out of the recieving end, it will all be in one chunk so how would I seperate the different values to be able to be used as parts of a MIDI message???
I will crack this.

I've found some code of a guy who has used the Mirf library to build a Body Air drum using pads and joystick movements. If I study his code I might get a good idea of whats going on. :slight_smile:
Cheers 4 now!

Also I realize that no matter what is coming out of the recieving end, it will all be in one chunk so how would I seperate the different values to be able to be used as parts of a MIDI message???

The idea is to put the data in the payload in a known order. Then, each byte in the payload received has a known meaning. Extract the data in the correct order to have the receiver have the same data that the sender sent.

Hi PaulS. Thanks for your help. I've been studying some code freom Honnet Body Air drum. A wireless project that converts pad hits and an analog joystick's x and y co-ords to MIDI. The project uses the teensy board and the joystick controls pitchbend but I have understood the code enough to change the Rx ends' MIDI.sendPitchbend() command to MIDI.senControlChange using midi controllers 102 and 103. Very nice results indeed. The code is below ( I am in contact with the guys whose project it is and they have been really nice. The code is on Github so Im sure they won't mind me posting my modifications here.
I now understand what you say about reading the payload bytes in the order they were sent. Now I just have to work out how to add more pots and switchpresses...
Here is the TX code:

#include <SPI.h>
#include "common.h"
#include "Mirf.h"
#include "nRF24L01.h"
#include "MirfHardwareSpiDriver.h"

#define DEBUG_LED
#define JOY_X A0
#define JOY_Y A1
#define N_PADS 4

typedef enum {
PAD1 = 18,
PAD2 = 19,
PAD3 = 20,
PAD4 = 21,
} pads_t;

bool padsPressed = false;
bool padsStates[N_PADS] = {false};
bool joyPressed = true;
uint16_t joyValX = 0;
uint16_t joyValY = 0;

void hello();
void readPads();
void readJoy();

void setup()
{
// with a 3.3V supply we need 8MHz instead of 16MHz
SET_CPU_FREQ;

Serial.begin(115200);

pinMode(LED, OUTPUT);
hello();

Mirf.spi = &MirfHardwareSpi;
Mirf.cePin = 48;
Mirf.csnPin = 49;
Mirf.init();
Mirf.setTADDR((byte*)ADDR);
Mirf.payload = PAYLOAD;
Mirf.config();
}

void loop()
{
static uint8_t buf[PAYLOAD];

readPads();
for (int i = 0; i < N_PADS; i++)
buf_ = padsStates* ? 1 : 0;_
_
readJoy();_
buf[N_PADS + 0] = (uint8_t)(joyValX >> 0);
buf[N_PADS + 1] = (uint8_t)(joyValX >> 8);
buf[N_PADS + 2] = (uint8_t)joyValY;
#ifdef DEBUG_LED*

* if (padsPressed || joyPressed)*
* digitalWrite(LED, HIGH);*
* else*
* digitalWrite(LED, LOW);*
#endif
* Mirf.send(buf);*
* while(Mirf.isSending());*
}
void readPads()
{
* padsPressed = false;*
* for (int i = 0; i < N_PADS; i++)
_
{_
_
if(digitalRead(PAD1 + i) == HIGH)_
_
{_
_ padsStates = true; //switch the led on only if one of the state was high*
* padsPressed = true;
}
else*
padsStates* = false;
}
}
void readJoy()
{_

uint16_t newJoyValX = 16383 - analogRead(JOY_X) * (16384 / 1023);
uint16_t newJoyValY = ABS(((analogRead(JOY_Y) >> 2) - 127));
_ newJoyValY = newJoyValY > 127 ? 127 : newJoyValY;*_

* joyPressed = false;*

* if (ABS(joyValX - newJoyValX) > (1 << 5))*
* {*
* joyValX = newJoyValX;*
* joyPressed = true;*
* }*

* if (ABS(joyValY - newJoyValY) > (1 << 3))*
* {*
* joyValY = newJoyValY;*
* joyPressed = true;*
* }*
}
void hello()
{
* for (int i = 0; i < 6; i++)*
* {*
* digitalWrite(LED, HIGH);*
* delay(50);*
* digitalWrite(LED, LOW);*
* delay(100);*
* }*
}
[/quote]
Here is Common.h ( variable defines )
> #ifndef COMMON_H
> # define COMMON_H
>
> #define CPU_PRESCALE(N) (CLKPR = 0x80, CLKPR = (N))
>
> #if F_CPU == 8000000
> # define SET_CPU_FREQ CPU_PRESCALE(0x01)
> #elif F_CPU == 16000000
> # define SET_CPU_FREQ
> #else
> # error "Unknown CPU frequency"
> #endif
>
> #define ABS(a) (((a) < 0) ? -(a) : (a))
>
> #define CE 10
> #define CSN 9
> #define ADDR "B.A.D"
>
> #define N_PADS 4
> #define N_JOYS 1
> #define PAYLOAD (N_PADS + 3 * N_JOYS)
> #define LED 11
>
> #endif
Here is RX code:
> #include <MIDI.h>
>
> #include <Mirf.h>
> #include <MirfHardwareSpiDriver.h>
> #include <MirfSpiDriver.h>
> #include <nRF24L01.h>
>
> #include <SPI.h>
> #include "common.h"
> #include "Mirf.h"
> #include "nRF24L01.h"
> #include "MirfHardwareSpiDriver.h"
>
> #define CHANNEL 1
>
> void hello();
>
> void setup()
> {
> // with a 3.3V supply we need 8MHz instead of 16MHz...
> SET_CPU_FREQ;
>
> pinMode(LED, OUTPUT);
> hello();
> MIDI.begin();
> Mirf.spi = &MirfHardwareSpi;
> Mirf.cePin = 7;
> Mirf.csnPin = 8;
> Mirf.init();
> Mirf.setRADDR((byte*)ADDR);
> Mirf.payload = PAYLOAD;
> Mirf.config();
> }
>
> void loop()
> {
> static uint8_t buf[PAYLOAD];
>
> static int padsNotes[N_PADS] = {42, 43, 44, 45};
> static bool padsStates[N_PADS] = {0};
> bool padsPressed = false;
>
> static int joyCtrls[2] = {0, 1};
> static uint16_t joyLastVals[2] = {0};
> uint16_t joyVals[2] = {0};
> bool pitchChanged = false;
>
> if(Mirf.dataReady())
> {
> Mirf.getData(buf);
>
> for (int pad = 0; pad < N_PADS; pad++)
> {
> if (buf[pad] && !padsStates[pad])
> {
> MIDI.sendNoteOn(padsNotes[pad], 50, CHANNEL);
> padsStates[pad] = true;
> padsPressed = true;
> }
> else if (!buf[pad] && padsStates[pad])
> {
> MIDI.sendNoteOff(padsNotes[pad], 0, CHANNEL);
> padsStates[pad] = false;
> }
> }
>
> joyVals[0] = (uint16_t)buf[N_PADS + 0] | ((uint16_t)buf[N_PADS + 1] << 8);
> joyVals[1] = buf[N_PADS + 2];
>
> if (joyVals[0] != joyLastVals[0])
> {
> MIDI.sendPitchBend(joyVals[0], CHANNEL);
> pitchChanged = true;
> joyLastVals[0] = joyVals[0];
> }
*> *
> if (joyVals[1] != joyLastVals[1])
> {
> MIDI.sendControlChange(joyCtrls[1], joyVals[1], CHANNEL);
> pitchChanged = true;
> joyLastVals[1] = joyVals[1];
> }
>
> // MIDI.send_now();
>
> if (padsPressed || pitchChanged)
> digitalWrite(LED, HIGH);
> else
> digitalWrite(LED, LOW);
>
> Mirf.flushRx();
> }
> }
>
> void hello()
> {
> for (uint8_t i=0; i<5; i++)
> {
> MIDI.sendNoteOn(42 + i, 255, CHANNEL);
> digitalWrite(LED, HIGH);
> delay(100);
> MIDI.sendNoteOff(42 + i, 255, CHANNEL);
> digitalWrite(LED, LOW);
> delay(50);
> }
> }
Good for a start!
Very nice. :slight_smile:
T8k care!

Finally got the code working after some modifications.:slight_smile:
Thanks to GitHub - honnet/BAD: Body Air Drum (AKA TapMe): a wireless MIDI instrument to wear on the body and thanks to everyone here on this forum.
The MEGA is now transmitting 3 pots, one LDR and 2 buttonpresses very easily and smoothly.
I have the revciever connected to my Audio interface on the MAC via a MIDI socket and a connection to 5V via a 220 Ohm resistor.
All works blindingly well!!
I will posta vbid on youtube in the next couple of days.:slight_smile:
Now to think about some sort of casing or expanding the project:)

I would like to post the final code on this message but I tried and I seem to run out of characters so I'll put in on another.

Cheers for now!
Steve.

Hi

I have been trying to compile the client server example of the Mirf library but it gives an error that Mirf was not declared in this scope. Can anyone tell me what is wrong.

This is the error that i get:

ping_client.pde: In function 'void setup()':
ping_client:39: error: 'Mirf' was not declared in this scope
ping_client:39: error: 'MirfHardwareSpi' was not declared in this scope
ping_client.pde: In function 'void loop()':
ping_client:77: error: 'Mirf' was not declared in this scope

Can anyone tell me what is wrong.

Sure. It looks like you haven't downloaded the Mirf library, or haven't installed it in the correct place.