Received data are correct on scope not in program - arduino

I use Arduino shiftIn instruction to receive data from a MLX90316.
It uses one wire for MOSI an MISO.
Data consists of 4 bytes (2+2)
First 2 bytes are an angle value. Second 2 bytes ares the reversed value of angle (1st complement)
First 2 bytes are correct on scope and program (0x00 and 0x22)
Second 2 bytes are correct on scope (0xFF and 0XDD), but are frequently (not always) wrong in program (0xFF and 0xDC or 0xFF and 0xCC...)
In fact only last byte is sometimes wrong when I print it.
I have tried to change Serial speed to 9600 bps (same result)
I have tried to change delayMicroseconds value before last shiftIn (same result)
/* MLX90316 Rotary Position Sensor */
int readAngle();
int pinSS = 10; // Green Wire
int pinDATA = 11; // Yellow Wire
int pinSCK = 13; // Grey Wire
unsigned int r1=0;
unsigned int r2=0;
unsigned int r3=0;
unsigned int r4=0;
int angle;
void setup(){
delayMicroseconds(16000); // 16ms slave start-up
pinMode(pinSS,OUTPUT); // Pin Slave Select
pinMode(pinSCK, OUTPUT); // Pin Clock
digitalWrite(pinSS, HIGH); // de-select chip
Serial.begin(115200);
Serial.println("MLX90316 Rotary Position Sensor");
}
void loop() {
angle = readAngle();
Serial.println("");
Serial.print("r1=");Serial.println(r1,HEX);
Serial.print("r2=");Serial.println(r2,HEX);
Serial.print("r3=");Serial.println(r3,HEX);
Serial.print("r4=");Serial.println(r4,HEX);
delay(10000);
}
int readAngle() {
// Start with clock LOW
digitalWrite(pinSCK, LOW);
// Data pin in write mode
pinMode(pinDATA, OUTPUT);
// take the SS pin low to select the chip:
digitalWrite(pinSS, LOW);
delayMicroseconds(30);
// Send START bytes
shiftOut(pinDATA, pinSCK, MSBFIRST, 0xAA);
delayMicroseconds(25);
shiftOut(pinDATA, pinSCK, MSBFIRST, 0xFF);
delayMicroseconds(30); // 30 us between START bytes and DATA
// Data pin in read mode
pinMode(pinDATA, INPUT_PULLUP);
// Receive data
r1 = shiftIn(pinDATA, pinSCK, MSBFIRST);
delayMicroseconds(25);
r2 = shiftIn(pinDATA, pinSCK, MSBFIRST);
delayMicroseconds(25);
r3 = shiftIn(pinDATA, pinSCK, MSBFIRST);
delayMicroseconds(30);
r4 = shiftIn(pinDATA, pinSCK, MSBFIRST);
// take the SS pin high to de-select the chip:
delayMicroseconds(5);
digitalWrite(pinSS, HIGH);
}
I expect the output of 0x00 0x22 0xFF 0xDD

I don't know which Arduino you are using but the shift in and out functions are very simple software implementations.
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
uint8_t value = 0;
uint8_t i;
for (i = 0; i < 8; ++i) {
digitalWrite(clockPin, HIGH);
if (bitOrder == LSBFIRST)
value |= digitalRead(dataPin) << i;
else
value |= digitalRead(dataPin) << (7 - i);
digitalWrite(clockPin, LOW);
}
return value;
}
The MLX90316 allows only a clock speed of 145kHz, so this direct port access could be too fast and the data is not ready when you read it.
But since you have a scope available you could simply check that timing and write your own shiftIn if necessary.
I think this "version" should work for your chip (untested)
uint8_t shiftIn2(uint8_t dataPin, uint8_t clockPin) {
uint8_t value = 0;
uint8_t i;
for (i = 0; i < 8; ++i) {
digitalWrite(clockPin, HIGH);
delayMicroseconds(4);
digitalWrite(clockPin, LOW);
value |= digitalRead(dataPin) << (7 - i);
delayMicroseconds(4);
}
return value;
}

Related

control relays using 74hc595(shiftout)

I want to use 7h4c595(8 IOs) to control 8 relays.
I tried using 0b00000000, It's working fine.
but I don't know how to concat switches values into this kind of binary.
almost 0 knowledge about this. sorry
I know the code below is not right, but it seems working.
problem: 74hc595's q0 is controling the 2nd relay, not the 1st.
and q1 is controling 3rd relay.
It should be like q0->1st, q1-> 2nd, and so on.
sorry for bothering you.
[code]
uint8_t switch0=0;// 0 = off
uint8_t switch1=1;// 1 = on
etc...
uint8_t switch7=1;//1-7 on
setup(){
etc...
}
loop(){
if(digitalWrite(btn1)==HIGH){
switch0=1;//on
switch1=0;//off
etc...//1-7 off
}
//unit8_t sw=0b10000000; //turn 1st relay on when btn1 pressed
uint8_t sw={switch0,switch1,....,switch7};
for(int i=0;i<8;i++){
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, i);
digitalWrite(latchPin, HIGH);
}
}
I'd go in similar way how are the pins defined in avr/io.h
constexpr uint8_t RELAY0 = 0;
constexpr uint8_t RELAY1 = 1;
// ...
constexpr uint8_t RELAY7 = 7;
loop() {
uint8_t data = (switch0 << RELAY0) | (switch1 << RELAY1) | /* ... |*/ (switch7 << RELAY7);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, data);
digitalWrite(latchPin, HIGH);
delay(200); // or more
}
Or you can use single byte (uint8_t) for storing all switches at once. As a bonus you can send it over shiftOut directly.
uint8_t allSwitches = 0; // all relays disabled
// turning relay x on (somewhere inside of function):
allSwitches |= _BV(x); // where x is number between 0 and 7 including
// turning relay x off:
allSwitches &= ~_BV(x);
// but you can set some of them and reset others in single step:
allSwitches = _BV(0) | _BV(5) | _BV(7); // turns on relay 0, 5 and 7, rest will be turned off

Controlling DC motor using encoder

I'm trying to control the speed of two DC motors using an Arduino Uno and encoders that are connected to the motors.
I've written a code to check whether there's a change in the position of the encoder and according to that calculate the velocity of the motors.
Ive used this website for the code:
I'm having problems when calculating the difference between the new position of the encoder and the old position of the encoder. For some reason that difference keeps going up even though the speed stays the same.
This is my code so far:
#define pwmLeft 10
#define pwmRight 5
#define in1 9
#define in2 8
#define in3 7
#define in4 6
//MOTOR A
int motorSpeedA = 100;
static int pinA = 2; // Our first hardware interrupt pin is digital pin 2
static int pinB = 3; // Our second hardware interrupt pin is digital pin 3
volatile byte aFlag = 0; // let's us know when we're expecting a rising edge on pinA to signal that the encoder has arrived at a detent
volatile byte bFlag = 0; // let's us know when we're expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set)
volatile long encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255
volatile long oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor)
volatile long reading = 0; //somewhere to store the direct values we read from our interrupt pins before checking to see if we have moved a whole detent
//MOTOR B
static int pinC = 12; // Our first hardware interrupt pin is digital pin 2
static int pinD = 33; // Our second hardware interrupt pin is digital pin 3
volatile byte cFlag = 0; // let's us know when we're expecting a rising edge on pinA to signal that the encoder has arrived at a detent
volatile byte dFlag = 0; // let's us know when we're expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set)
volatile long encoderPosB = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255
volatile long oldEncPosB = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor)
volatile long readingB = 0;
int tempPos;
long vel;
unsigned long newtime;
unsigned long oldtime = 0;
void setup() {
//MOTOR A
pinMode(pinA, INPUT_PULLUP); // set pinA as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
pinMode(pinB, INPUT_PULLUP); // set pinB as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
attachInterrupt(0, PinA, RISING); // set an interrupt on PinA, looking for a rising edge signal and executing the "PinA" Interrupt Service Routine (below)
attachInterrupt(1, PinB, RISING); // set an interrupt on PinB, looking for a rising edge signal and executing the "PinB" Interrupt Service Routine (below)
//MOTOR B
pinMode(pinC, INPUT_PULLUP); // set pinA as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
pinMode(pinD, INPUT_PULLUP); // set pinB as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
attachInterrupt(0, PinC, RISING); // set an interrupt on PinA, looking for a rising edge signal and executing the "PinA" Interrupt Service Routine (below)
attachInterrupt(1, PinD, RISING);
Serial.begin(9600); // start the serial monitor link
pinMode (in1, OUTPUT);
pinMode (in2, OUTPUT);
pinMode (in3, OUTPUT);
pinMode (in4, OUTPUT);
digitalWrite (8, HIGH);
digitalWrite (9, LOW); //LOW
digitalWrite (7, LOW); //LOW
digitalWrite (6, HIGH);
pinMode (pwmLeft, OUTPUT);
pinMode (pwmRight, OUTPUT);
}
void PinA(){
cli(); //stop interrupts happening before we read pin values
reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB's values
if(reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
encoderPos --; //decrement the encoder's position count
bFlag = 0; //reset flags for the next turn
aFlag = 0; //reset flags for the next turn
} else if (reading == B00000100) bFlag = 1; //signal that we're expecting pinB to signal the transition to detent from free rotation
sei(); //restart interrupts
}
void PinB(){
cli(); //stop interrupts happening before we read pin values
reading = PIND & 0xC; //read all eight pin values then strip away all but pinA and pinB's values
if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
encoderPos ++; //increment the encoder's position count
bFlag = 0; //reset flags for the next turn
aFlag = 0; //reset flags for the next turn
} else if (reading == B00001000) aFlag = 1; //signal that we're expecting pinA to signal the transition to detent from free rotation
sei(); //restart interrupts
}
void PinC(){
cli(); //stop interrupts happening before we read pin values
readingB = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB's values
if(readingB == B00001100 && cFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
encoderPosB --; //decrement the encoder's position count
dFlag = 0; //reset flags for the next turn
cFlag = 0; //reset flags for the next turn
} else if (readingB == B00000100) dFlag = 1; //signal that we're expecting pinB to signal the transition to detent from free rotation
sei(); //restart interrupts
}
void PinD(){
cli(); //stop interrupts happening before we read pin values
readingB = PIND & 0xC; //read all eight pin values then strip away all but pinA and pinB's values
if (readingB == B00001100 && dFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
encoderPosB ++; //increment the encoder's position count
dFlag = 0; //reset flags for the next turn
cFlag = 0; //reset flags for the next turn
} else if (readingB == B00001000) cFlag = 1; //signal that we're expecting pinA to signal the transition to detent from free rotation
sei(); //restart interrupts
}
void loop(){
analogWrite(pwmLeft, motorSpeedA);
analogWrite(pwmRight, motorSpeedA);
if(oldEncPos != encoderPos) {
newtime = millis();
tempPos = encoderPos - oldEncPos;
vel = tempPos / (newtime - oldtime);
Serial.println(tempPos);
oldEncPos = encoderPos;
oldtime = newtime;
delay(250);
}
if(oldEncPosB != encoderPosB) {
Serial.println(encoderPosB);
oldEncPosB = encoderPosB;
}
}
The two if statements are just made to check that the encoders are working properly. In the first if statement I'm trying to do the calculations of the velocity.
I would appreciate any feedback.
Thank you.
EDIT:
I found out theres an encoder library which makes everything a lot easier.
so now my code looks like this:
#include <Encoder.h>
#define pwmLeft 10
#define pwmRight 5
Encoder myEncA(3, 2);
Encoder myEncB(13, 12);
unsigned long oldtimeA = 0;
unsigned long oldtimeB = 0;
int speedA = 100;
int speedB = 130;
void setup() {
Serial.begin(9600);
digitalWrite (8, HIGH);
digitalWrite (9, LOW); //LOW
digitalWrite (7, LOW); //LOW
digitalWrite (6, HIGH);
pinMode (pwmLeft, OUTPUT);
pinMode (pwmRight, OUTPUT);
}
long oldPositionA = -999;
long oldPositionB = -999;
void loop() {
analogWrite(pwmLeft, speedA);
analogWrite(pwmRight, speedB);
long newPositionA = myEncA.read();
long newPositionB = myEncB.read();
if ((newPositionA != oldPositionA) || (newPositionB != oldPositionB)) {
unsigned long newtimeA = millis ();
long positionA = newPositionA - oldPositionA;
long positionB = newPositionB - oldPositionB;
long velB = (positionB) / (newtimeA - oldtimeA);
long velA = (positionA) / (newtimeA - oldtimeA);
oldtimeA = newtimeA;
oldPositionA = newPositionA;
oldPositionB = newPositionB;
Serial.println(velB);
}
}
I am still having problems with my "B" motor, the calculation is still way off for some reason.
Motor "A" works fine
A couple of issues, including a divide by zero error in loop(). This scan cause a reset of your controller. Always check the value of the divisor when doing a division!
Using only positive transitions unnecessarily reduces the resolution of your readings by 2.
The Arduino is an 8bit controller... Reading an int requires multiple instruction, which means you should disable interrupts before reading an int that's modified by an interrupt routine. Failure to do so will cause odd jumps in the vakue read. This is usually done like this:
//...
NoInterrupts();
int copyOfValue = value; // use the copy to work with.
interrupts();
//...
In your case, a single byte value is likely enough to store movement, with a reset every 30 ms, this should give you a top speed of 255 pulses/30ms = 8500 pulses/second or 1275000 rpm for a 24 ticks/turn encoder. :) in that case, no need to disable interrupts for a reading.
with one reading per 30ms, 1 tick /30ms = 33 tick/seconds, or 85 RPM. It's a bit high for motion. You may need to average readings, depending on your application.
Also, the algorithm you are using will definitely not work. The main reason is that the delay between reads and adjustments is too small. Most readings will be of zero. You will run into the problem when removing the println() calls. I suggest a pacing of at least 30 ms between readings. 100 ms may work a bit better, depending on your application. Using a float variable for speed average will definitely help.
void loop()
{
//...
if(oldEncPos != encoderPos) {
newtime = millis();
tempPos = encoderPos - oldEncPos;
vel = tempPos / (newtime - oldtime); // <-- if newtime == oltime => divide by zero.
//...
}
//...
}
The encoder reading code seems awfully complex...
#define PIN_A 2 // encoder bit 0
#define PIN_B 3 // encoder bit 1
volatile char encVal1;
volatile unsigned char encPos1; // using char
void OnEncoder1Change()
{
char c = (digitalRead(pinA) ? 0b01 : 0)
+ (digitalRead(pinB) ? 0b10 : 0); // read
char delta = (c - encVal1) & 0b11; // get difference, mask
if (delta == 1) // delta is either 1 or 3
++encPos1;
else
--encPos1;
encVal1 = c; // keep reading for next time.
encPos1 += delta; // get position.
// no need to call sei()
}
setup()
{
pinMode(pinA, INPUT_PULLUP);
pinMode(pinB, INPUT_PULLUP);
// get an initial value
encValA = digitalRead(pinA) ? 0b01 : 0;
encValA += digitalRead(pinB) ? 0b10 : 0;
// use digitalPinToInterrupt() to map interrupts to a pin #
// ask for interrupt on change, this doubles .
attachInterrupt(digitalPinToInterrupt(PIN_A), OnEncoder1Change, CHANGE);
attachInterrupt(digitalPinToInterrupt(PIN_B), OnEncoder1Change, CHANGE);
//...
}
unsigned char oldTime;
unsigned char oldPos;
int speed;
void loop()
{
unsigned char time = millis();
if (time - oldTime > 30) // pace readings so you have a reasonable value.
{
unsigned char pos = encPos1;
signed char delta = pos - oldPos;
speed = 1000 * delta) / (time - oldTime); // signed ticks/s
encPos1 -= pos; // reset using subtraction, do you don't miss out
// on any encoder pulses.
oldTime = time;
}
}

Arduino Interrupt misbehaving

I'm having some problems with some C code I'm writing for an arduino project. The goal is to digitize a large quantity of analog signals with external multiplexed ADCs, then load these digital values into an external shift register and shift them into the Arduino using SPI.To test my code I only have one ADC multiplexing 4 signals.
The interrupt pin (20) is connected to a comparator circuit which looks at the raw analog signal and pulls the pin high when the voltage is 1V or higher. When the ISR is called it will disable global interrupts "noInterrupts()" set an event flag, detach pin 20 from the interrupt handler, enable global interrupts "interrupts()" and finally return to where it left off.
I'm facing a couple issues, first the ISR is called once fine, a second time fine but after the second ISR call it is not called again untill, which is my seconds issue, the interrupt pin goes low. As per the AttachInterupt() function the ISR should only be called when pin 20 is high. This can be seen in the first and second picture I have attached. Another thing I notice is that the duration that the interrupt pin is high has no effect on whether a 3rd ISR is called.
I'm not sure if this is an issue with my understanding of the interrupt-handling of the Arduino, or a code screw up resulting in a stack overflow or something like that.
// the sensor communicates using SPI, so include the library:
#include <SPI.h>
//Constants
#define RD 41 //pin 41 conneced to read pin
#define INT1 37 //pin 37 connecte to interrupt 1
#define CLK_INH 53 //pin 53 connected to clk inhibit
#define LD 40 //pin 40 connected to load pin
#define INPUT_MAX 3 //input selector limit (Zero Indexed)
#define SENSORS 3 //how many sensors are used (Zero Indexed)
#define DATA_DUMP 38 //pin 29 controlls the data dump deature
#define BYTE_LEN 1 //number of ADC used
#define DEBUG1 17
#define DEBUG2 16
//Controls
unsigned char selector = 0; //ACD input selector
volatile byte eventFlag = LOW; //Control Flag, set to True when event occurs
bool lastButtonState = true;
//Counters
unsigned int i = 0; //eventLog[i]: event counter
unsigned int j = 0; //eventLog[i].data[j]: data counter
//Function Delcarations
unsigned char inputSelector (unsigned char my_selector);
void lockAndPop ();
void dataDump ();
void debug (int pin);
bool fallingEdge (bool); //check for a falling edge of a digital read
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
// put your setup code here, to run once:
pinMode(RD, OUTPUT); //Read pin, 0 = begin analog conversion (ADC)
pinMode(INT1, INPUT); //Interrupt pin, 0 = conversion complete (ADC)
pinMode(CLK_INH, OUTPUT); //Clock inhibit pin, 1= no change on output (ShiftRegister)
pinMode(LD, OUTPUT); //Shift/Load pin, 1 = data is shifted (ShiftRegister)
pinMode(DATA_DUMP, INPUT);
pinMode(DEBUG1, OUTPUT);
pinMode(DEBUG2, OUTPUT);
DDRA = 0xFF; //Set port A to ouput
SPI.begin();
//SPI.mode1 Clock idel low CLOP = 0, Data sampled on falling edge CPHA = 1
SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE1));
digitalWrite(RD, HIGH); //Stop conversion
digitalWrite(CLK_INH, HIGH); //No change on the output
digitalWrite(LD, LOW); //Load the shift register
digitalWrite(DEBUG1, LOW);
digitalWrite(DEBUG2, LOW);
attachInterrupt(digitalPinToInterrupt(20), pin_ISR, HIGH); //Call pin_ISR when pin20 goes high
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct //event structure, containts a timestamp element and an array of 18 data points
{
unsigned long int timeStamp;
unsigned char data[SENSORS];
} Event;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Event eventLog[200]; //an array of structures representing 200 events, once the 200 events have been filled the data will be printed
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
if(fallingEdge(digitalRead(DATA_DUMP))){ //If there is falling edge on the data dump button, call the dataDump function
dataDump();
}
debug(DEBUG2);
if(eventFlag) //if the Event flag is set to true by ISR begin the conversion steps
{
debug(DEBUG1);
digitalWrite(RD,LOW); //Start conversion
while(digitalRead(INT1)){} //Wait for conversion to complete
eventLog[i].timeStamp = micros();
for (j=0; j<=SENSORS; j++) {
lockAndPop(); //lock digital value and reset conversion
PORTA = inputSelector(selector); //increment the selector pin
digitalWrite(RD, LOW); //Start new conversion
digitalWrite(CLK_INH, LOW); //Start the data transfer
eventLog[i].data[j] = SPI.transfer(0); //read a single byte from the SPI line
digitalWrite(CLK_INH, HIGH); //Inhibit clock
digitalWrite(LD, LOW);
while(digitalRead(INT1)){} //wait for previous conversion to end
}
i++;
digitalWrite(RD, HIGH);
selector = 0;
if(i>=200){
dataDump(); //if the event log hits 200 before a data dump is request, dump the data
}
eventFlag = LOW;
attachInterrupt(digitalPinToInterrupt(20), pin_ISR, HIGH);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void pin_ISR() {
noInterrupts();
detachInterrupt(digitalPinToInterrupt(20));
eventFlag = HIGH;
interrupts();
return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
unsigned char inputSelector (unsigned char my_selector){
if(my_selector==INPUT_MAX){ //if the current selector is at the highest value reset to 0
return 0;
}
return my_selector++; //increment the input selector by 1
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void lockAndPop (){
digitalWrite(LD, HIGH); //Lock in digital value
digitalWrite(RD, HIGH); //Reset conversion
return;
}
void dataDump (){
detachInterrupt(digitalPinToInterrupt(20));
char buf[100], *pos = buf; //create a buffer of 100 charaters, anda pointer to the begining of that buffer
char *base = buf; //create a base address to reset the buffer
unsigned int eventCount = i; //how many events occured before dump command was called
unsigned int localCount;
unsigned int localData;
Serial.begin(115200);
Serial.println(i);
for (localCount = 0; localCount<=eventCount; localCount++){
pos += sprintf(pos, "%lu", eventLog[localCount].timeStamp); //sprintf will append the data to the pointer "pos", and return the number of byte append.
for (localData = 0; localData<=SENSORS; localData++){
pos += sprintf(pos, " %d", (unsigned int)(eventLog[localCount].data[localData]));
}
Serial.println(buf);
pos = base;
}
i=0;
j=0;
Serial.end();
attachInterrupt(digitalPinToInterrupt(20), pin_ISR, HIGH);
return;
}
void debug(int pin){
digitalWrite(pin, HIGH);
digitalWrite(pin, LOW);
return;
}
bool fallingEdge (bool currentButtonState){
if(!currentButtonState&&lastButtonState){
lastButtonState = currentButtonState;
return 1;
}
lastButtonState = currentButtonState;
return 0;
}
There is a bit of noise happening on the ISR pin, but this shouldn't matter as I'm disabled that particular pin within the service routine so I wouldn't think this is an issue

Arduino RF Data Transmission

I have 3 ultrasonic sensor connected to 1 Arduino Uno device. I want to send their data to another Arduino Uno with RF transmitter. I want to send the sensor's id number (1,2,3) and the data (0 or 1).
I want to transmit the data from printDistance method but the message that transmitter sends is char *msg. Do I have to send only char values?
#include <VirtualWire.h>
#undef int
#undef abs
#undef double
#undef float
#undef round
//Sonar 1
int echoPin1 =2;
int initPin1 =3;
int distance1 =0;
//Sonar 2
int echoPin2 =6;
int initPin2 =7;
int distance2 =0;
//Sonar 3
//int echoPin3 =8;
//int initPin3 =9;
//int distance3 =0;
void setup() {
// Initialise the IO and ISR
vw_set_ptt_inverted(true); // Required for RF Link module
vw_setup(2000);
vw_set_tx_pin(8);
pinMode(initPin1, OUTPUT);
pinMode(echoPin1, INPUT);
pinMode(initPin2, OUTPUT);
pinMode(echoPin2, INPUT);
// pinMode(initPin3, OUTPUT);
// pinMode(echoPin3, INPUT);
// pinMode(initPin4, OUTPUT);
// pinMode(echoPin4, INPUT);
delay(2000);
Serial.begin(9600);
Serial.println(" ");
}
void loop() {
const char *msg; // this is your message to send
vw_send((uint8_t *)msg, strlen(msg));
vw_wait_tx(); // Wait for message to finish
delay(200);
distance1 = getDistance(initPin1, echoPin1);
printDistance(1, distance2);
delay(10);
distance2 = getDistance(initPin2, echoPin2);
printDistance(2, distance2);
delay(10);
//distance3 = getDistance(initPin3, echoPin3);
//printDistance(3, distance3);
//delay(10);
// distance4 = getDistance(initPin4, echoPin4);s
// printDistance(4, distance4);
Serial.println(" ");
delay(5000);
// Serial.println(" ");
}
int getDistance (int initPin, int echoPin){
digitalWrite(initPin, HIGH);
delayMicroseconds(10);
digitalWrite(initPin, LOW);
delayMicroseconds(5);
unsigned long pulseTime = pulseIn(echoPin, HIGH);
int distance = pulseTime/58;
return distance;
}
void printDistance(int id, int dist){
Serial.print('<');
Serial.print( id );
Serial.print( '>' );
if (dist >= 30 || dist <= 0 ){
Serial.print("0");
}else {
Serial.print("1");
}
Serial.print('<');
Serial.print( '/' );
Serial.print( id );
Serial.print( '>' );
// Serial.println(" ");
}
uint8_t vw_send(uint8_t* buf, uint8_t len) sends an array of bytes, with maximum length 77. In C, the type for a byte is called char. In AVR, this has an alias uint8_t as well.
So you send an array of bytes, and it is up to you to decide how the chars in the array are interpreted. For example, you could use sprintf() to write numbers as ascii encoded strings. Then on the receiving end, you would have to use atoi() to get the number back out of the string.
You could also choose to simply fill the array with the actual number values. With this option, you have to break up ints into separate bytes, and combine them back together on the receiving end. In your particular case, the data already fits into bytes, so you don't have to do that.
Beware that vw_send((uint8_t *)msg, strlen(msg)); won't work correctly with this second method. strlen() will count up to the first byte that holds a 0, effectively truncating the array. You would only use this call when using the sprintf() approach.
It looks like you are sending the data for all three sensors at the same time, and that the data for each is either 0 or 1. Why not send a 3-byte message of 0s and 1s?
uint8_t msg[3];
msg[0] = 0;
msg[1] = 1;
msg[2] = 0; // fill these in as you like
vw_send(msg, 3);
I couldn't add code to comment.
I changed the code as this;
void printDistance(int id, int dist){
uint8_t msg[1];
if (dist >= 30 || dist <= 0 ){
msg[0] = 0;
vw_send(msg, 1);
//vw_wait_tx();
}else {
msg[0] = 1;
vw_send(msg, 1);
//vw_wait_tx();
}

How to control an Mcp41010 wiper position with an analog value

I am using an Mcp41010 digipot chip and am wondering how to vary the wiper position of the chip with an analog input voltage that I can adjust, I need a way of decrementing(--) the wiper position if the voltage goes over a certain point and incrementing(++) the wiper position of the chip back to the normal position this is some code that i found that just fades the wiper position up and down I need a way of controlling it. I am still very new to arduino so sorry if my explanation was clear enough.
int CS_signal = 12; // Chip Select signal onsul pin 2 of Arduino
int CLK_signal = 52; // Clock signal on pin 4 of Arduino
int MOSI_signal = 51; // MOSI signal on pin 5 of Arduino
byte cmd_byte2 = B00010001 ; // Command byte
int initial_value = 100; // Setting up the initial value
void initialize() { // send the command byte of value 100 (initial value)
spi_out(CS_signal, cmd_byte2, initial_value);
}
void spi_out(int CS, byte cmd_byte, byte data_byte){ // we need this function to send command byte and data byte to the chip
digitalWrite (CS, LOW); // to start the transmission, the chip select must be low
spi_transfer(cmd_byte); // invio il COMMAND BYTE
delay(2);
spi_transfer(data_byte); // invio il DATA BYTE
delay(2);
digitalWrite(CS, HIGH); // to stop the transmission, the chip select must be high
}
void spi_transfer(byte working) {
for(int i = 1; i <= 8; i++) { // Set up a loop of 8 iterations (8 bits in a byte)
if (working > 127) {
digitalWrite (MOSI_signal,HIGH) ; // If the MSB is a 1 then set MOSI high
} else {
digitalWrite (MOSI_signal, LOW) ; } // If the MSB is a 0 then set MOSI low
digitalWrite (CLK_signal,HIGH) ; // Pulse the CLK_signal high
working = working << 1 ; // Bit-shift the working byte
digitalWrite(CLK_signal,LOW) ; // Pulse the CLK_signal low
}
}
void setup() {
pinMode (CS_signal, OUTPUT);
pinMode (CLK_signal, OUTPUT);
pinMode (MOSI_signal, OUTPUT);
initialize();
Serial.begin(9600); // setting the serial speed
Serial.println("ready!");
}
void loop() {
for (int i = 0; i < 255; i++) {
spi_out(CS_signal, cmd_byte2, i);
Serial.println(i); delay(10);
}
for (int i = 255; i > 0; --i) {
spi_out(CS_signal, cmd_byte2, i);
Serial.println(i);
delay(10);
}
}
int CS_signal = 12; // Chip Select signal onsul pin 2 of Arduino
int CLK_signal = 52; // Clock signal on pin 4 of Arduino
int MOSI_signal = 51; // MOSI signal on pin 5 of Arduino
byte cmd_byte2 = B00010001 ; // Command byte
int initial_value = 100; // Setting up the initial value
void initialize() { // send the command byte of value 100 (initial value)
spi_out(CS_signal, cmd_byte2, initial_value);
}
void spi_out(int CS, byte cmd_byte, byte data_byte){ // we need this function to send command byte and data byte to the chip
digitalWrite (CS, LOW); // to start the transmission, the chip select must be low
spi_transfer(cmd_byte); // invio il COMMAND BYTE
delay(2);
spi_transfer(data_byte); // invio il DATA BYTE
delay(2);
digitalWrite(CS, HIGH); // to stop the transmission, the chip select must be high
}
void spi_transfer(byte working) {
for(int i = 1; i <= 8; i++) { // Set up a loop of 8 iterations (8 bits in a byte)
if (working > 127) {
digitalWrite (MOSI_signal,HIGH) ; // If the MSB is a 1 then set MOSI high
} else {
digitalWrite (MOSI_signal, LOW) ; } // If the MSB is a 0 then set MOSI low
digitalWrite (CLK_signal,HIGH) ; // Pulse the CLK_signal high
working = working << 1 ; // Bit-shift the working byte
digitalWrite(CLK_signal,LOW) ; // Pulse the CLK_signal low
}
}
void setup() {
pinMode (CS_signal, OUTPUT);
pinMode (CLK_signal, OUTPUT);
pinMode (MOSI_signal, OUTPUT);
initialize();
Serial.begin(9600); // setting the serial speed
Serial.println("ready!");
}
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
if(sensorValue <= 200){
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float voltage = sensorValue * (5.0 / 1023.0);
// print out the value you read:
Serial.println(voltage);
int i = sensorValue;{
spi_out(CS_signal, cmd_byte2, i);
Serial.println(i);
}
}
}

Resources