/* M328P_Master_ultrasonic_and_i2c_scanner.ino by Lucas Lim created on 10/5/2020 Purpose: 1) To detect i2c nodes 2) To receive, calculate the distance in cm and send reading to slave via I2C bus 3) To display reading to I2C LCD display module via I2C bus too The work is provided for academic purpose for Fab Academy 2020. Users accept all as is, no warranty is provided, no call/email from users will get a response. Users accept all liability. */ #include #include // i2c nodes address on the network #define i2c_lcd 63 #define i2c_slave 2 LiquidCrystal_I2C lcd(i2c_lcd, 16, 2); // set the LCD address, for a 16 chars by 2 rows display int trigPin = 7; // Trigger (PD7 - arduino pin no. 7) int echoPin = 8; // Echo (PB0 - arduino pin no. 8) long duration, cm; const int ledPin = 2; // PD2 - Arduino pin no. 2 byte c1 = 0; // for requestFrom() void blink_led(int times) { while(times--) { digitalWrite(ledPin, HIGH); delay(350); digitalWrite(ledPin, LOW); delay(350); } } void i2c_scan_nodes() { // scan for LCD Wire.beginTransmission (i2c_lcd); if (Wire.endTransmission() == 0) { lcd.setCursor(2, 0); lcd.print("LCD ready"); delay(3000); lcd.clear(); } Wire.endTransmission(); // scan for I2C Slave Wire.beginTransmission (i2c_slave); if (Wire.endTransmission() == 0) { lcd.setCursor(1, 0); lcd.print("Slave detected"); delay(3000); lcd.clear(); } // if return = 2 : received NACK on transmit of address // if return = 4 : other error else if (Wire.endTransmission() ==2 || Wire.endTransmission() ==4) { lcd.setCursor(0, 0); lcd.print("Slave not found!"); delay(3000); lcd.clear(); } Wire.endTransmission(); Wire.requestFrom(i2c_slave, 1); while(Wire.available()) { c1 = Wire.read(); // receive a byte from Slave # 2 } lcd.setCursor(2, 0); lcd.print("slave # "); lcd.setCursor(9, 0); lcd.print(i2c_slave); lcd.setCursor(2, 1); lcd.print("received : "); lcd.setCursor(13, 1); lcd.print(int(c1)); if (c1 == i2c_slave) { delay(2000); // to facilitate the recording of video, this can be deleted blink_led(3); // blink led to indicate receive of acknowledgement (or data) from Slave } delay(2000); lcd.clear(); } void sensor() { // The sensor is triggered by a HIGH pulse of 10 or more microseconds. // Give a short LOW pulse beforehand to ensure a clean HIGH pulse: digitalWrite(trigPin, LOW); delayMicroseconds(5); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // Read the signal from the sensor: a HIGH pulse whose // duration is the time (in microseconds) from the sending // of the ping to the reception of its echo off of an object. pinMode(echoPin, INPUT); duration = pulseIn(echoPin, HIGH); // Convert the time into a distance cm = duration *0.034/2; } // Display ultrasonic sensor reading to LCD void lcd_display(int cm) { lcd.setCursor(4,1); lcd.print(" "); // clear the previous reading lcd.setCursor(4,1); lcd.print(cm); } // send reading to Slave # 2 void send_reading(int msg) { Wire.beginTransmission(i2c_slave); Wire.write(msg); Wire.endTransmission(); } void setup() { delay(2000); // to facilitate the recording of video, this can be deleted // join i2c bus as master, no address is require Wire.begin(); // Initialize the LCD, must be called in order to initialize I2C communication // lcd.begin(); // LCD library for ATTiny45 lcd.init(); // LCD library from Arduino // Turn on the backlight lcd.backlight(); // blink LED (this must be setup calling i2c_scan_nodes) pinMode(ledPin, OUTPUT); // scan for presence of I2C LCD and Slave node i2c_scan_nodes(); // display static text info for distance reading // these text doesn't change on LCD lcd.setCursor(2, 0); lcd.print("Distance is"); lcd.setCursor(8,1); lcd.print("cm"); // setup ultrasonic sensor pins pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); } void loop() { // activate sensor and receive reading data sensor(); //send reading to SLAVE # 2 send_reading(cm); lcd_display(cm); // slow down for easy reading delay(800); }