Skip to content

13. Networking

Group Assigment

This week’s group assignment was to send a message between group projects. To do this, Angelina Yang and I just connected our individual projects for this week. The documentation for this week’s group assignment can be found here.

Assignment

This week’s individual assignment was to connect wired or wireless nodes with network or bus addresses. I attempted a couple different ways of using I2C.

I2C Between 2 ATtiny412s

For a long time, I tried to get I2C between 2 ATtiny412s to work. Because of my original input in inputs week, I had some experience with I2C, but still did not really understand it. Some of the parts of the proccess involved in these attempts is documented in my Week 11 (Inputs Week) Documentation. I wanted to use the same boards I used for my input for my I2C networking between boards. After I made the two boards discussed in my Week 12 documentation, I realized that I needed a pull-up resisitor on both SCL and SDA for I2C to work properly. Because of this, I designed and milled three of a new board. This is the design:

For reference, this is Adrian Torres’ design:
However, after milling and soldering these, I realized that these pull-up resistors would interfere with the TX and RX pins used for the step response sensor, as the pins I chose to use for TX and RX were also SDA and SCL. Luckily, this meant my old, originally thought defunct boards, could actually come in handy. However, for I2C only, I continued to try with the boards which included the pull-up resistors. I designed these boards so that, in theorey, as many of them could be connected in a row, all using the same power, ground, SCL, and SDA. This is what the boards looked like after soldering:
I used Adrian Torres’ code and changed it around with the help of Copilot and even some of my classmates for quite a few hours, but could not get any indication of communication. I verified that all the lines were properly connected with a multimeter, but still got nothing. My classmate Connor Cruz, who got I2C to work between two ATtiny412s and a RP2040, checked over my code, wiring, and boards, and did not know what was the problem. Additionally, Mr. Adam Durrett, my AP Computer Science Principles teacher and likely the most skilled with electronics at our lab, who had gotten I2C between two ATtiny412s working before, and was using it for a current project, could not figure out the issue.

I2C Between ATtiny412 and Seeed Xiao RP2040

Eventually, I decided I should try to get I2C working between an ATtiny412 and a RP2040 as an RP2040 can connect to Serial Monitor, which allows for a much easier debugging process, as it is easier to tell what is working and what is not. I began by creating a board for both the ATtiny412 and the RP2040. I had the ATtiny412 board also have headers allowing it to simultaneously connect to a step response, as I’ve decided I want to utilize this in my final project. Here are the two boards I made:

I then milled out these boards and soldered them. Next, I programmed the boards to simply blink an LED:

However, I accidentally fried the RP2040, and the soldering job was kind of sketchy anyway, so I remilled a new one, and took an RP2040 from an old, failed board. I also ensured that the Serial connection to the RP2040 worked well before proceeding. Now that I had both boards working well, I needed to reattempt programming I2C. After a lot of trial and error and help from Adrian Torres’ documentation as well as some helpful and some misleading information from Microsoft Copilot, I arrived at this code, which had the RP2040 as the master, along with comments for some brief explanations I added in afterwards:


#include  // library for I2C

#define SLAVE_ADDRESS 8 // address assigned to slave in its code upon Wire.begin initialization

void setup() {
  Wire.begin(); // join i2c bus (my code worked when I removed master's address but idk if you can have it)
  pinMode(D8, OUTPUT); // initalizing LED output (not used in this code so not revelant)
}

void loop() {
  Wire.beginTransmission(SLAVE_ADDRESS); // transmit to device
  Wire.write(1); // write 1
  Wire.endTransmission();    // stop transmitting
  delay(500); // delay in between transmissions
  Wire.beginTransmission(SLAVE_ADDRESS); // transmit to device
  Wire.write(0); // write 0
  Wire.endTransmission();  // stop transmitting
  delay(1000); // delay in between transmissions
}

And this was my code for the ATtiny412 as a slave:


int d1=0;
int LED=4;

#include 

void setup() {
  Wire.begin(8); // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
  pinMode(LED, OUTPUT);
  Wire.onReceive(recieveEvent);
}

void loop() {
  if (d1==1) {
  digitalWrite(LED, HIGH);
  }
  else {
  digitalWrite(LED, LOW);
  }
}

void recieveEvent(int howMany)
{
  while (Wire.available())
  {
    d1 = Wire.read();
  }
}

And this is the video of I2C finally working:

My code is very similar to Adrian Torres’, as I wanted to deviate from what is sure to work as little as possible. However, after this I began incorporating different elements into the code. I began by getting the ATtiny412 to send messages to the RP2040. This took a little time, but I eventually arrived at this code for the RP2040 as a slave:


#include 
#define SLAVE_ADDRESS 8
#define Master_address 9
int c = 0;

void setup() {
Wire.begin(9);
Serial.begin(9600);
Wire.onReceive(recieveEvent);
}

void loop() {
}

void recieveEvent(int howMany)
{
  while (Wire.available())
  {
    c = Wire.read();
    Serial.println(c);
  }
}

And this was the code for the ATtiny412 as a master:


int d1=0;
int LED=4;
#define Master_address 9
#define SLAVE_ADDRESS 8

#include 

void setup() {
  Wire.begin();
  pinMode(LED, OUTPUT);
}

void loop() {
  Wire.beginTransmission(Master_address); 
  Wire.write(1);
  Wire.endTransmission();
  delay(500);
  Wire.beginTransmission(Master_address);
  Wire.write(0);
  Wire.endTransmission();
  delay(1000);
}

Both are very similar to how they were with the RP2040 as the master, except I wanted to Serial print the message when it was received from the ATtiny412, so that is why I included the Serial.println(c). This way it is much easier to see what is going on. Here is a video of the RP2040 receiving 1s and 0s through I2C and printing them to the Serial monitor on Arduino.

Networking with Input

I then attached my Flubben II board (made in Inputs Week) to the ATtiny412 board so that I could measure inputs from this step response and then communicate them to the RP2040. After a lot of failed attempts, I got the input working and the boards to communicate simultaneously, however, the readings the Serial Monitor showed were very different than the actual readings. Here is the code I used for the RP2040 (basically the same as above):


#include 
int c = 0;
#define SLAVE_ADDRESS 8
#define Master_address 9
#include 
void setup() {
Serial.begin(9600);
Wire.begin(9); // join i2c bus (address optional for master)
Wire.onReceive(recieveEvent);
}
void loop() {
}

void recieveEvent(int howMany)
{
  while (Wire.available()) {
    c=Wire.read();
    Serial.print(c);
  }
  Serial.println();
}


And this is the code I used for the ATtiny412, integrating the input code into the I2C code:


int LED=4;
#define rxpin 1 // RX pin on ATtiny412
#define txpin 0 // TX pin on ATtiny412
#define settle 100 // Time for voltage to settle
#define samples 100 // How many samples of analogRead it takes in given time
#define Master_address 9
#define SLAVE_ADDRESS 8

#include 

void setup() {
  Wire.begin(); // join i2c bus (address optional for master)
  pinMode(LED, OUTPUT);  
  pinMode(txpin, OUTPUT); // Initializing the TX pin as OUTPUT (for sending signals through TX and recieving and measuring those same signals and their strengths through RX)
}

void loop() {
  long int avg = average(); // Takes one sample of average() function 
  instantCheck();
  Wire.beginTransmission(Master_address); // transmit to device #4
  Wire.write(average());
  Wire.endTransmission();    // stop transmitting
  delay(1000);
}

long int average() { // Function to find the average change in signal
  long int up, down, avg; 
   avg = 0; // Initializing avg as 0
   noInterrupts(); // Disables all other activities
   for (int i = 0; i < samples; i++) { // For loop which loops (samples) times
      digitalWrite(txpin, HIGH); // Sends signal through TX pin
      up = analogRead(rxpin); // Recieves signal through RX pin
      delayMicroseconds(settle); // Delays for 100 microseconds so that signal can level out
      digitalWrite(txpin, LOW); // Takes away signal from TX
      down = analogRead(rxpin); // Reads RX pin after removing signal
      delayMicroseconds(settle); // Delays again so that signal can level out
      avg += up - down; // Measuring capacitance of system as in theory avg should be 0 if copper plates were connected
   }
   interrupts(); // Allows other activites to occur again
   return avg; // Returns the avg value
}

void instantCheck() { // Function to simply check functionality of the program
  long int avg = average(); // Takes one sample of average() function
  if (avg > 7080 ) { // If capacitance over 
    digitalWrite(4, LOW); 
  }
  else {
    digitalWrite(4, HIGH); 
  }
}


And here is a video of the readings I was seeing on the Serial Monitor:

Generally, the readings appeared somewhat random between about -100 and 100, although when I put my hand really close or touched the Flubben II board it would generally read a high value negative number for about two readings before reverting back to normal. Overall, there was no significant enough correlation or pattern from the readings that I could deduce. I know this is an issue in the I2C connection because, when I fine-tuned the conditional argument if (avg>7080) to 7080 (it often changes depending on the surrondings), the LED would consistently turn on as I moved my hand close to the board, and turn off otherwise, so the avg value had to be consistenly around 7080 +-20-50. To try to troubleshoot, I attempted to send the message “Hello” from the ATtiny412 to the RP2040 through I2C. When I tried to print this on the Serial Monitor, it came up with all sorts of symbols and plain squares (meaning it did not understand the message), confirming my suspicion that something was wrong with the I2C. However, for now I will be happy that I got I2C working and an input connected to it.

Week Reflection

This week was a long struggle, but eventually saw a satisfying outcome. Although I never got I2C working between two ATtiny412s, I got working what I will likely use in my final project and learned a lot about I2C and other methods of networking in the process. Now that I am confident in my capabilities revolving around the designing and creation of applicable boards, in the future I will try to focus my time more on the software side of things, where I could learn a whole lot more (and likely more applicable skills), instead of overloading my time with monotonous board development.

File Downloads

You can download the files used in the processes included in this documentation here.


Last update: June 22, 2024