arduino as slave

I have a robot car. And on the robot car is a servo motor with a small circuit board attached to the wing. On the circuit board I have an attiny85 which is to drive both the Servo motor as well as an SR-04 ultrasound range finder.

I am trying to get the data of the range finder to car’s CPU, an Mboard. So I can read out the sensor on the Serial monitor (http://imall.itead.cc/im121126001.html)
Besided the small “issue” that the stupid Mboard is working on 3V3 and the sensor isn’t… I have am having a small problem between the communication between the 2 arduinos. Though I can get it working, the sensor function can take up to 7ms to get a range. But this delay interrupts with my coomunication

The master code is:

#include <Wire.h>

void setup() {
  Serial.begin(38400);
  Wire.begin();

}

void loop() {
  byte j;
  for (int i = 0; i < 256; i++) {
    Wire.beginTransmission(0x26);
    Wire.write(i);
    Wire.endTransmission();
    

    Wire.requestFrom(0x26, 1);
    delay(7);    
    if (Wire.available()) {
      j = Wire.read();
      
      Serial.print(i, HEX); Serial.print("  ");
      Serial.println(j, HEX);
    }
    delay(500);
  }
}

and the slave code

#include <TinyWireS.h>
#include <usiTwiSlave.h>

//#include "Servo8Bit.h"  << is not working either...
byte range;


#define SET(x) (PORTB |= 0x01 << x)    // macros for setting and clearing pins of port B0-B4
#define CLR(x) (PORTB &= ~0x01 << x)

#define echoPin 3

int maximumRange = 200; 
int minimumRange = 0;
long duration = 1000, distance; 

//Servo8Bit servo;


void setup() {
  TinyWireS.begin(0x26);
  //servo.attach(1);
  
DDRB = 0b10111; // makes B3 input and the rest outputs

}

void loop() {
  
  range = ultraSound();
  


if (TinyWireS.available()){           // got I2C input!
   TinyWireS.receive();               // clears the received byte from the buffer
   
    TinyWireS.send(range);           // sends the range value

  }
}

byte ultraSound()
{
  /*CLR(4);
  delayMicroseconds(2);

  SET(4);
  delayMicroseconds(10);

  CLR(4);
  //duration = pulseIn(echoPin, HIGH, 7000);*/
  
  distance = duration / 58.2;  // = 11 becuz distance = 1000
  
  return(distance); // returns 11 ATM     < so far this works
}

The problem lies in the function ultraSound() when it takes to much time. I have no I2C commincation at all. the 12 us delay and the 3 port instrucions are already enough to disrupt the bus.

How can I run a function which freezes the program for ~7ms and send the range over the I2C bus?

edit: I am using a logic analizer for debugging

Besided the small "issue" that the stupid Mboard is working on 3V3 and the sensor isn't.

Which sensor? The ultrasonic sensor? Have you actually tried it at 3.3V?

Though I can get it working, the sensor function can take up to 7ms to get a range.

Maybe you need to speed up sound in your neck of the woods.

   delay(7);

The sensor takes too long, but it's OK to waste time here?

   delay(500);

and here?

The sensor does not work at 3.3V. I tested it, ...thinking about puttin a 1.5V batter in series with the VCC to buff the voltage to 4.8V... I'm not in the mood to solder a voltage regulator on it...

the delay(7) and delay(500) are both in the master code this doesnt matter. I want to send my sensor data to the serial monitor that is why I put a delay of 500 in the mastercode. I dont need 100 sensor readings on my screen every second. That delay(7) is basically not doing anything it was for testing..

I am talking about the slave code, the slave causes the problem. I want the slave to take a sensor scan, say every ~20ms. Than I want to ask the last sensor data of the slave with my master..

I think I just figured out the solution

void loop()
{
  ultraSound();
  while(!TinyWireS.available()) {}
  
  if (TinyWireS.available()){           // got I2C input!
     TinyWireS.receive();               // get the byte from master

     TinyWireS.send(range);             // send it back to master
    }
}

withwhile(!TinyWireS.available()) {} I put the slave program on hold untill the master asks for the last sensor reading. After the slave has send it's data, it takes a new sensor reading and wait for the master again..

The polling frequency of the master than becomes the scanning frequency of the slave. I just ask for data every 20ms and im done..

I am still having the problem.

#include <TinyWireS.h>
#include <usiTwiSlave.h>

//#include "Servo8Bit.h"
byte byteRcvd, yolo = 1;


#define SET(x) (PORTB |= 0x01 << x)
#define CLR(x) (PORTB &= ~0x01 << x)

#define echoPin 3

int maximumRange = 200, pos; // Maximum range needed
int minimumRange = 0; // Minimum range needed
long duration = 1000, distance; // Duration used to calculate distance

//Servo8Bit servo;


void setup() {

  //servo.attach(1);
  //Serial.begin (9600);
  DDRB = 0b10111;
  PORTB = 0b10000;
  TinyWireS.begin(0x26);
}

void loop()
{
  if (TinyWireS.available()) {
    while(TinyWireS.available()) {
      TinyWireS.receive();         // reads out the buffer until it is empty
    }

    TinyWireS.send(distance);           // send the variabele 'distance' back to master
    
    /*delay(1);

    CLR(4);
    delayMicroseconds(2);

    SET(4);
    delayMicroseconds(10);

    CLR(4);
    duration = pulseIn(echoPin, HIGH, 3000); // 3 ms timeout  << 
    if (duration == 0) duration = 3000; // if timeout occurse, PulseIn returns a 0

    distance = duration / 58.2;*/  // cant get higher than 51
  }
}

Like now the attiny works without flaws, but when put the commented code back in, all communication is gone. The master initiates a data tranfer every 500 ms. The only thing what this program does, is doing this line of code if (TinyWireS.available()) < this waits on the master

As soon as the master sends a byte, the slave sends something back. All the code under TinyWireS.send(distance); does not take 500ms, it takes about 3ms + 12us . So in theory there is more than enough time to make a scan with the range finder before the program has to be ready for a new incomming byte.

I cannot figure out why the program stops working if I out-comment the code and try to use the sensor. The sensor code on it’s own works

I found the problem, and it is rediculous. It makes no sense. The reason why there was no I2C communication is that you apparantly cannot use an OR or AND instruction on PORTB. As soon as I commented all SET and CLR macros out of the program, I2C was running again. Than I replaced the macros by normal PORT instructions like PORTB |= 0x10; and this also was one big error.

I removed the macros
#define SET(x) (PORTB |= 0x01 << x)
#define CLR(x) (PORTB &= ~0x01 << x)

And now I use:
PORTB &= ~_BV(PB4);
PORTB |= _BV(PB4);

And this actually solved the ******* problem :angry:

I would like to ask the writer of TinyWireM and TinyWireS: what daf*q???