I am fairly new to Arduino development, and I am trying to build a small system from two Arduino UNO boards where I send data from one board to the other.
I use laser as a medium. On the first board, I have some data (say an array for now), that I want to send to the other side. I am using a simple UART-like protocol; I have a start bit, eight data bits, and my idle state. My idle state is high (laser is on), and then I have my start bit (low), then my eight data bits. I set my array to change the state of a pin on the board through a for loop with 100ms delay (bit time) between each bit and the following one.
Here is my sender code:
#define LASERPIN 13
void setup() {
pinMode (LASERPIN, OUTPUT);
digitalWrite (LASERPIN, HIGH); //IDLE
delay(10000);
uint8_t bits[] = {HIGH, LOW, HIGH, LOW, HIGH, LOW, HIGH, LOW}; //to send
//start bit
digitalWrite (LASERPIN, LOW);
delay(100);
for (int i = 0; i < 8; i++) {
digitalWrite (LASERPIN, bits[i]);
delay(100);
}
//back to IDLE
digitalWrite(LASERPIN, HIGH);
delay(10);
}
void loop() {
}
I know it seems that it doesnt make sense to have what I have in setup(), but I only need my code to run once (sort of a dirty fix).
I don't think there are errors in my sender code, but I attached it just in case.
Now, on the receiver side. I have a photodiode that is connected to a comparator that tests whether i received a high or a low bit. VCC on the opamp is 5 volts, and GND is zero, my reference voltage on it is somewhere around 3.3 volts. The photodiode's voltage when laser is pointed at it is close to 5 volts, and 0.20 volts in ambient conditions.
The mechanism of operation on the receiver side is that I have attached an interrupt to the pin that the opamp's output is connected to, and whenever it detects a falling edge (transition from idle to start bit) it starts a 150ms timer to sample the first bit (after the start bit), then triggers a 100ms timer to sample the remaining bits.
Here is the receiver code:
#define START 2
#define DATA 3
volatile uint8_t i = 0;
volatile uint8_t a[8];
volatile bool reading[8] ;
volatile byte reading1 = 0;
void setup() {
Serial.begin(9600);
cli();
//set timer1 interrupt at 10Hz
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; //initialize counter value to 0
// set compare match register for 1500hz (1.5ms) increments
OCR1A = 37502;// = (16*10^6) / (6.66666666667*64) - 1
TCCR1B |= (1 << WGM12); // turn on CTC mode
TCCR1B |= (1 << CS11) | (1 << CS10); // Set CS10 and CS11 bits for 64 prescaler
// TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
sei();
attachInterrupt(digitalPinToInterrupt(START), startISR, FALLING);
pinMode(START, INPUT);
pinMode(DATA, INPUT);
}
void loop() {
}
void startISR() {
detachInterrupt(digitalPinToInterrupt(START));
// Serial.print("Start ISR entered\n");
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
}
ISR(TIMER1_COMPA_vect) {
OCR1A = 24999; // (1ms) interrupt every 1ms to sample bits
if (i < 8) {
//a[i] = digitalRead(DATA);
a[i] = (digitalRead(DATA));
i++;
// Serial.print("data ISR entered \n");
Serial.print(reading[i]);
// Serial.println();
}
else {
TIMSK1 |= (0 << OCIE1A);
// Serial.println();
}
}
My problem is that whatever I receive on the photodiode, the output on the serial monitor will be 00000008.
I have tried so many things (data types, different approaches to reading, ...etc.) but nothing seems to work.
From an electronics view point, I have made sure everything is working; I have used an oscilloscope to check what signal I'm sending, and it was correct (timing-wise), and I checked the output of the opamp using the scope, and the frame I got was identical to what I have sent.
Could anyone please check my codes and try to explain to me what could have went wrong? I'm suspecting there could be an error in my reading logic; as in the way I am saving the pin values.
A potential error I am suspecting is that timers aren't configured correctly, and I have thought about letting the ISR that reads data toggle a digital pin and have that pin connected to an oscilloscope and see what I get on the screen and measure the time per bit, but I don't have an oscilloscope at my disposal now to verify.