Skip to content

Instantly share code, notes, and snippets.

@dragonlock2
Created August 19, 2019 22:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dragonlock2/6c691bc0acdd57ce0ce8567d596a251c to your computer and use it in GitHub Desktop.
Save dragonlock2/6c691bc0acdd57ce0ce8567d596a251c to your computer and use it in GitHub Desktop.
Code for Nunchuk remote
//RGB setup
#define R 9 //all are pwm pins
#define G 6
#define B 5
//RF24 stuff
#define RF24_INT 3 //INT1
#define RF24_CE 7
#define RF24_CSN 10
//MPU6050 stuff
#define MPU_INT 2 //INT0
MPU6050 mpu; //default address 0x68
//chip is placed rotated forward 180deg
//Battery stuff
#define BATT A7 //V = 3.3 * val / 1023
//Control stuff
#define JOY_X A1 //map to 1 byte
#define JOY_Y A0
#define BUT_C A3 //needs pullups
#define BUT_Z A2
#define JOY_X_LOW 0
#define JOY_X_CENTER 520
#define JOY_X_HIGH 1023
#define JOY_Y_LOW 0
#define JOY_Y_CENTER 515
#define JOY_Y_HIGH 1023
#define JOY_MAPPED_LOW 0
#define JOY_MAPPED_CENTER 127
#define JOY_MAPPED_HIGH 255
#include <SPI.h>
#include <RF24.h>
#include <math.h>
RF24 radio(7, 8);
const byte addr[6] = "12345";
struct Dat { //limited to 32 bytes
uint8_t batteryVoltage; //v = batteryVoltage / 100
uint8_t joyXPos;
uint8_t joyYPos;
uint8_t butC;
uint8_t butZ;
int16_t ax, ay, az;
int16_t gx, gy, gz;
} dat; //creates instance dat
void setup() {
Serial.begin(115200);
while(!Serial);
radio.begin();
radio.setChannel(125);
radio.setPALevel(RF24_PA_MAX);
radio.setDataRate(RF24_250KBPS);
radio.enableDynamicPayloads();
radio.openReadingPipe(0, addr);
radio.startListening();
attachInterrupt(1, doRadio, FALLING);
}
void loop() {
}
void teensySwapVars() { //teensy swaps byte order compared to avr
dat.ax = dat.ax << 8 | (dat.ax >> 8 & 0x00FF);
dat.ay = dat.ay << 8 | (dat.ay >> 8 & 0x00FF);
dat.az = dat.az << 8 | (dat.az >> 8 & 0x00FF);
dat.gx = dat.gx << 8 | (dat.gx >> 8 & 0x00FF);
dat.gy = dat.gy << 8 | (dat.gy >> 8 & 0x00FF);
dat.gz = dat.gz << 8 | (dat.gz >> 8 & 0x00FF);
}
void doRadio() {
bool tx, fail, rx;
radio.whatHappened(tx, fail, rx);
if (radio.available(0)) {
radio.read(&dat, sizeof(dat));
teensySwapVars();
double g = sqrt(1.0*dat.ax*dat.ax + 1.0*dat.ay*dat.ay + 1.0*dat.az*dat.az) / 4096;
Serial.print(g);
Serial.print(" ");
Serial.print(dat.batteryVoltage / 100.0);
Serial.print(" ");
Serial.print(dat.joyXPos);
Serial.print(" ");
Serial.print(dat.joyYPos);
Serial.print(" ");
Serial.print(dat.butC);
Serial.print(" ");
Serial.print(dat.butZ);
Serial.print(" ");
Serial.print(dat.ax);
Serial.print(" ");
Serial.print(dat.ay);
Serial.print(" ");
Serial.print(dat.az);
Serial.print(" ");
Serial.print(dat.gx);
Serial.print(" ");
Serial.print(dat.gy);
Serial.print(" ");
Serial.print(dat.gz);
Serial.println();
}
}
#include <SPI.h>
#include <RF24.h>
#include "I2Cdev.h"
#include <Wire.h>
#include "MPU6050.h"
#include "Constants.h"
const byte addr[6] = "12345";
RF24 radio(RF24_CE, RF24_CSN);
struct Dat { //limited to 32 bytes
uint8_t batteryVoltage; //v = batteryVoltage / 100
uint8_t joyXPos;
uint8_t joyYPos;
uint8_t butC;
uint8_t butZ;
int16_t ax, ay, az;
int16_t gx, gy, gz;
} dat; //creates instance dat
void setup() {
OSCCAL = 0xAD; //specific for each device
Serial.begin(115200); //possible with calibrated internal RC
RGB_setup();
RF24_setup(); //could potentially use ack packets
MPU6050_setup();
Control_setup();
}
void loop() {
dat.batteryVoltage = 330 * (long) analogRead(BATT) / 1023; //casting as long bc overflow error
//interesting c++ does math as ints first then converts to long
dat.joyXPos = getJoy_X();
dat.joyYPos = getJoy_Y();
dat.butC = !digitalRead(BUT_C);
dat.butZ = !digitalRead(BUT_Z);
mpu.getMotion6(&dat.ax, &dat.ay, &dat.az, &dat.gx, &dat.gy, &dat.gz);
radio.startWrite(&dat, sizeof(dat), 0);
}
//interrupt methods
void doRadio() {
bool tx, fail, rx;
radio.whatHappened(tx, fail, rx);
digitalWrite(R, !tx);
digitalWrite(G, tx);
}
//general methods
uint8_t getJoy_X() {
int val = constrain(analogRead(JOY_X), JOY_X_LOW, JOY_X_HIGH);
if (val <= JOY_X_CENTER) {
return map(val, JOY_X_LOW, JOY_X_CENTER, JOY_MAPPED_LOW, JOY_MAPPED_CENTER);
} else {
return map(val, JOY_X_CENTER, JOY_X_HIGH, JOY_MAPPED_CENTER, JOY_MAPPED_HIGH);
}
}
uint8_t getJoy_Y() {
int val = constrain(analogRead(JOY_Y), JOY_Y_LOW, JOY_Y_HIGH);
if (val <= JOY_Y_CENTER) {
return map(val, JOY_Y_LOW, JOY_Y_CENTER, JOY_MAPPED_LOW, JOY_MAPPED_CENTER);
} else {
return map(val, JOY_Y_CENTER, JOY_Y_HIGH, JOY_MAPPED_CENTER, JOY_MAPPED_HIGH);
}
}
void RGB_setup() {
pinMode(R, OUTPUT);
pinMode(G, OUTPUT);
pinMode(B, OUTPUT);
for (int i = 0; i < 4; i++) {
digitalWrite(B, HIGH);
delay(70);
digitalWrite(B, LOW);
delay(70);
}
}
void RF24_setup() {
radio.begin();
radio.setChannel(125); //outside range of wifi
// radio.setPayloadSize(6); //not necessary with dynamic payloads
radio.setPALevel(RF24_PA_MAX); //max power
radio.setDataRate(RF24_250KBPS); //lowest speed, longest range
radio.enableDynamicPayloads();
radio.openWritingPipe(addr);
attachInterrupt(digitalPinToInterrupt(RF24_INT), doRadio, FALLING);
}
void MPU6050_setup() {
Wire.begin();
Wire.setClock(400000); //400kHz
mpu.initialize();
mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_16);
mpu.setFullScaleGyroRange(MPU6050_GYRO_FS_2000);
mpu.setXGyroOffset(34);
mpu.setYGyroOffset(26);
mpu.setZGyroOffset(25);
mpu.setXAccelOffset(-1416);
mpu.setYAccelOffset(-2640);
mpu.setZAccelOffset(1135);
mpu.setXFineGain(15);
mpu.setYFineGain(36);
mpu.setZFineGain(-33);
}
void Control_setup() {
pinMode(BUT_C, INPUT_PULLUP);
pinMode(BUT_Z, INPUT_PULLUP);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment