Why don't my tinkercad code work

Hi all. Im new to using the arduino code so i have started simple by trying to control the direction of a motor over the i2c bus. I have simulated it in tinkercad and its not reading my code or something. I have attached my tinkercad file below.

Welcome to the forum.

A link to a Tinkercad project usually fails.
This is what I get:

Can you show the sketch here ? Put the sketch between code-tags. For code-tags use the '</>' button or put the sketch between lines with three single backslash quotes.

```
Your sketch
```

If you have multiple Arduino boards, then show all the sketches of all the boards.

Can you try to make a screendump of the Tinkercad circuit and show it to us ? So we can see what your project is.

O sorry about that.

My master sketch is as follows.

<#include <Wire.h>

int x;
int y;
int c;

void setup() {
  pinMode(12,INPUT_PULLUP);
  pinMode (7,INPUT_PULLUP);
  Wire.begin(); 
  Serial.begin(9600);
}
void loop() {
  x = digitalRead(12);
  y = digitalRead(7);
  if (x == LOW && y ==HIGH){c = 1;}
  if (y == LOW && x ==HIGH){c = 2;}
  if (x == HIGH && y == HIGH){c = 3;}
  
  Wire.beginTransmission(9);//9 here is the address of the slave board 
  Wire.write(c);//Transfers the value to the slave board
  Wire.endTransmission();

And my slave sketch is as follows.

#include <Wire.h>


int c;


void setup() {
  pinMode (13, OUTPUT);//Connect LED to pin 13
  pinMode (7, OUTPUT);
  Wire.begin(9);//9 here is the address(Mentioned even in the master board code) 
  Serial.begin(9600);
}
void receiveEvent(int bytes) {
  c = Wire.read();//Receive value from master board
  
}
void loop() {
  
  Wire.onReceive(receiveEvent);
  
  if (c==1){digitalWrite(13, HIGH);
  digitalWrite(7, LOW);
  }
  if (c==3){digitalWrite(7, HIGH);
  digitalWrite(13, LOW);       
  }
  if (c=2){digitalWrite(13, LOW);
  digitalWrite(7, LOW);
}
  delay(1000);
    Serial.write(c);
}

Here is also a screen shoot of my circuit diagram.

Thanks for looking at this for me

Can you tell what your goal is ?
To learn how to control a motor ? :arrow_right: use just one Arduino board
To learn more about the I2C bus ? :arrow_right: :grimacing:

The I2C is not really meant as a communication bus between processors. But the Arduino Uno has a reliable Slave mode, and you made a good effort. I think it can work :smiley:

Master:
You are flooding the I2C bus with I2C actions. You need to give the Slave some time to breath, so it can run properly. A delay in the Master of 1ms will already help, I suggest to add a delay in the loop() of 500ms.

Slave:
Installing the onReceive handler should be done just once in setup(). Can you move this line to setup(): Wire.onReceive(receiveEvent);
You don't need a delay in loop(), if you only act when something needs to be done.
We use a "flag" for that, a boolean variable.

bool gotNewData = false;

void receiveEvent(int bytes)
{
  c = Wire.read();     // Receive value from master board
  gotNewData = true;   // raise the flag, so the loop() knows there is new data  
}

void loop() 
{
  if (gotNewData)
  {
    // do something with the received data.
    // set a digital pin
    // write something to the serial port
    ...
   
    // clear the flag
    gotNewData = false;

    // do not add a delay !
    // keep the Slave responsive and acting fast, without delay.  
  }
}

Could you add leds to pin 13 and 7 of the Slave ? I think that will be useful.

[ADDED]
Oops, it should be a '==' here instead of '=':

if (c=2)

My goal for this circuit and code is to get the i2c bus working on this small scale so I can use the i2c protocol in an underwater ROV project where 10+ inputs need to be condensed and transmitted through a few wires from the surface to the sub were these messages need to be uncoded into outputs.

That comuncaciom protcole do you recment for this?

below is a photo of the full circuit diagram for the full project.

it's working perfectly now I've done those changes you suggested. Thank you so much.

Looking at the circuit, a lot of things get my attention. Is it okay if I mention them here ? Maybe some are useful for you.

  1. For such a project you need to draw a schematic. KiCad is free and there are online schematic drawing sites. The time to learn KiCad is not wasted.
  2. Buttons or switches can be with one pin to GND. Then you can use INPUT_PULLUP for pinMode() and add extra pullup resistor of 4k7 or 10k for a real project. A Pullup resistor is between the button and the 5V pin (for a 5V Arduino board).
  3. Leds needs resistors.
  4. Will your real project have 9V batteries ? Those are weak. They might last 5 minutes (if you are lucky) or not work at all.
  5. Are the potentiometers connected to A1 and A2 and those pins have also pulldown resistors ? Why the pulldown ?
  6. It is okay to use resistors of 100k instead of 1k for a voltage divider to measure the battery voltage.
  7. Is that a FSR at the Slave board ? It is connected to 5V and A0, that will not work.
  8. One servo motor is powered by the 3V3 pin and the other servo motor is powered by the VIN pin. That's just wrong. Using the 5V pin is also wrong, the Arduino board can not deliver enough current. Even a small servo motor can have a peak current of 500mA. That is too much for a Arduino board.
  9. By using pin 0 and 1 on both boards, you can not send debug messages to the Serial Monitor with Serial.println(). You really need the ability to send debug messages. Find another way. Add extra hardware for more input/output pins.
  10. On this forum we see projects fail because the I2C bus is used between two Arduino boards when there are motors in the project. If you have extra hardware for more input/output pins, can you do your project with a single Arduino board ?
  11. Mosfets drivers for motors are more reliable than relays.

I wrote something on Github about a I2C bus, it is to scare you for the trouble that might be ahead :scream:

hi.
I believe I have fixed all of those errors. Thanks for looking over it.

I am planning on using an Arduino mega for this project so I will have plenty of pins to utilize, I have only modeled it with an Arduino UNO as that is all tinkercad had in their component library.

I am planning on making a semantic of the circuits as I am hopping on getting a PCB printed to act as a shield for the Arduinos to reduce the complexity of the wiring needed.

How would I find all the pin locations on the Arduino mega to ensure the shield fits?

As with the 9V battery, they will be replaced in the final project as well. just using them as tinkercad has a limited component library.

This is the same story with the FSR which is just taking the place of a simple pressure sensor that will be used in the final.

The servo wiring is a mess as one of the servos is taking the place of what will be an ESC in the final project. The ESC I am going to use connects to the battery and the moters well also having an output voltage supply for the controller, hens the positive is attached to the VIN pin. I will move the other servo voltage supply to the VIN as well which will stop any posbeal excessive current draw on the board.

I have also been doing some research on other communication systems and have seen serial communication used to communicate between bards with the ade of an HC-12 or a RS 485 module. Just wondering what your thoughts are on using this system instead of i2c as the transmission distance will be 50+ meters.

Thank you so much for your help.

That is better :smiley:
Try not to waste too much time with the I2C communication.

Can you try to find a prototype shield for the Mega board ? Arduino is open source, but I can only find shorter shields.

I'm not sure what you want to do with the VIN pin :face_with_raised_eyebrow: What is the voltage that you are going to use ?
Some power a Arduino board with a step-up-step-down converter that outputs 5V and power the Arduino board with 5V to its 5V pin (not officially recommended, current might flow into the computer via the USB cable).
Some use 12V to power a Arduino board. Then the voltage regulator on the Mega board might get too hot.

What is 50+ meters ? About 50.01 meters or three times around the world :rofl:
The RS-485 is a good bus. There is also a Arduino library for it, but I don't know if that is compatible with the Arduino Mega. If there is Wifi, then the ESP32 might be possible. For small data packages over a longer range is LoRa communication.

I recommend to keep a I2C bus below 50 cm, but if there are multiple problems with the I2C bus, then 50 cm might already be too much. If it is longer than 10 cm, then you already have to know about the troubles of the I2C bus.

The Wokwi simulator has: Mega board, I2C display, buttons, potentiometers, relays, servo motors, leds. It is missing a DC motor, you would have to use leds instead of a DC motor. Sharing a project and continue with a project from someone else is very easy with Wokwi.

Hi, I hope you are having a fantastic Xmas holiday.

I've been doing some work on the ROV controller and for some reason, I can only get one pin on each joystick to operate and print to the serial monitor as designed. only pin LJ_S and pin RJ_S funcion as intended.

// left joystick
const byte LJ_A = 2;
const byte LJ_W = 3;
const byte LJ_D = 4;
const byte LJ_S = 5;
// right joystick
const byte RJ_A = 10;
const byte RJ_W = 11;
const byte RJ_D = 12;
const byte RJ_S = 13;

// truster controles
byte T1; //front left
byte T2; //left lift
byte T3; //back left

byte T4; //front right
byte T5; //right lift
byte T6; //back right

// exstrass
byte fowd_ = 1;
byte stop_ = 3;
byte back_ = 5;


void setup() {

pinMode (2, INPUT_PULLUP);
pinMode (3, INPUT_PULLUP);
pinMode (4, INPUT_PULLUP);
pinMode (5, INPUT_PULLUP);
pinMode (10, INPUT_PULLUP);
pinMode (11, INPUT_PULLUP);
pinMode (12, INPUT_PULLUP);
pinMode (13, INPUT_PULLUP);

Serial.begin (9600);

delay (100);
}

void loop() {

  // left joystick
  
  if (digitalRead(LJ_A) == LOW){ T1 = back_, T3 = fowd_ ;}

  if (digitalRead(LJ_W) == LOW){ T1 = fowd_, T3 = fowd_ ;}

  if (digitalRead(LJ_D) == LOW){ T1 = fowd_, T3 = back_ ;}

  if (digitalRead(LJ_S) == LOW){ T1 = back_, T3 = back_ ;}

  else (T1 = stop_, T3 = stop_ );

  Serial.print("front_left_moter = ");
  Serial.println(T1);
  Serial.print("back_left_moter = ");
  Serial.println(T3);
  
  delay (500);
  
  // right joystick
  if (digitalRead(RJ_A) == LOW){ T4 = back_, T6 = fowd_ ;}

  if (digitalRead(RJ_W) == LOW){ T4 = fowd_, T6 = fowd_ ;}

  if (digitalRead(RJ_D) == LOW){ T4 = fowd_, T6 = back_ ;}

  if (digitalRead(RJ_S) == LOW){ T4 = back_, T6 = back_ ;}

  else (T4 = stop_, T6 = stop_ );

  Serial.print("front_right_moter = ");
  Serial.println(T6);
  Serial.print("back_right_moter = ");
  Serial.println(T4);
  
  delay (500);
  
}

It is hard to share a Tinkercad project. You can invite someone else to work on your project, but if you show that link here on the forum, then everyone can change your project. I think it is possible to make a project public.

The circuit should work, setup() seems okay. Can you write normal code in the loop() and add messages ?

Use 8 of these:

  if (digitalRead(LJ_A) == LOW)
  {
    Serial.print("LJ_A, ");
    T1 = back_;
    T3 = fowd_ ;
  }

The line below has about 4 bugs hanging around it (it is only part of the last "if" so the if-if-if-else is not working, I have never seen a "else" with '(' and ')', you probably have learned about the comma in school but we use it only when needed, it is not clear what the "else" should do and a explanation is missing, the fifth bug is that it is ugly.

else (T1 = stop_, T3 = stop_);

If your sketch works, you can try to put the buttons in an array. Then you don't have to repeat the code 8 times.

How would i go about using an array for this sketch. Could you please provide some example code.

Thanks for your help. Its so exciting to see the project gaining some head way.

You can put the buttons in a matrix and use the Keypad library. Here is an example: https://create.arduino.cc/projecthub/jehankandt/arduino-keypad-4x4-70fca5.

Or you can use them as normal buttons with an array.
In the code below, I translate one array to other arrays, but I don't like it :face_with_raised_eyebrow:

const int buttons[8] = { 2,3,4,5,10,11,12,13};

const int arrayT1[4] = { back_, fowd_, fowd_, back_ };
const int arrayT2[4] = { 0, 0, 0, 0};
const int arrayT3[4] = { fowd_, fowd_, back_, back_ };
const int arrayT4[4] = { back_, fowd_, fowd_, back_ };
const int arrayT5[4] = { 0, 0, 0, 0 };
const int arrayT6[4] = { fowd_, fowd_, back_, back_ };

void setup()
{
  for( int i=0; i<8; i++)
  {
    pinMode( buttons[i], INPUT_PULLUP);
  }
}

void loop()
{
  for( int i=0; i<8; i++)
  {
    if( digitalRead( buttons[0]) == LOW)
    {
      if( i < 4)                           // first four buttons ?
      {
        j = i;
        T1 = arrayT1[j]; 
        T2 = arrayT2[j];
        T3 = arrayT3[j];
      }
      else
      {
        j = i - 4;
        T4 = arrayT4[j]; 
        T5 = arrayT5[j];
        T6 = arrayT6[j];
      }
    }
  }
}

I think that you should not use it in that way. The arrays for the T1 ... T6 are probably not needed, because they have some kind of logic. I use a single array for all 8 buttons and in the loop() I split the buttons into two parts, I think there is a prettier way to do that.

The way that you handle the buttons in the code, depends on if you want to be able to press multiple buttons at the same time.

Ok excellent. Thanks for the demo code. Its always useful to read through examples.

I have got the code the work by usind most of my old code. I changed the formatting the the previous example you suggested and replace the else statements with more if statements.

For some reason the else statements were messing everything up.

I have ordered all the hardware i need for this first stage of the project so real life testing will start soon. :slightly_smiling_face::slightly_smiling_face:

I'm just wondering if you could guide me through sending an array over a rs 485 module as i think this will be the best way for all communications to be carried out.

Thanks so much for your time.

Can you show the new sketch ? So I can see how many bugs there are left around the "else".
afbeelding

For RS-485, find a good library and look at the examples that come with the library.
There is a Arduino RS-485 library for the RS-485 MKR shield. That library is very simple, it has no node addressing. Perhaps you don't need that ?

Ok, excellent I will have a look at some example libraries for the rs 485.

this is my almost completed code for the controller hath of the project. the joystick controls work perfectly now but for some reason, the lights_on_LED is not actvating when the switch is turned on.
Is there a way I can limit any bugs in the code or things I can do differently to get better results in future codes?


// ROV controller code for arduin uno.

// TO DO
// - send all controlers over i2c to slave and LCD

#include <Wire.h>

#include <LiquidCrystal.h>

// pin alcaciones
const byte controler_voltag = A0;
const byte camra_tillt = A1;
const byte speed_controle = A2;
const byte light_swich = A3;
const byte lights_on_LED = A4;
const byte controler_battrry_low = A5;

// left joyestick
const byte LJ_A = 2;
const byte LJ_W = 3;
const byte LJ_D = 4;
const byte LJ_S = 5;
// center joystuck
const byte CJ_S = 6;
const byte CJ_A = 7;
const byte CJ_W = 8;
const byte CJ_D = 9;
// right joystick
const byte RJ_A = 10;
const byte RJ_W = 11;
const byte RJ_D = 12;
const byte RJ_S = 13;

// constant alcaciones
// truster controles
byte T1; //front left
byte T2; //left lift
byte T3; //back left

byte T4; //front right
byte T5; //right lift
byte T6; //back right

// exsesrey moters
byte G_R_M; //griper moter
byte B_C_M; //boinsey compncater moter
byte L_V_M; //levling moter

// truster speed
byte T_speed;

// camra tilt
byte cam_tilt;

// lights
bool light_state;

// battreys
float C_V; //controler voltag
float R_V; // ROV voltage

// words

// exstrass
byte fowd_ = 1;
byte stop_ = 3;
byte back_ = 5;

// darta transmicion
int controll_code[2] { T1, T2 };

// voltage mesring
const unsigned long voltage_read_intveal = 30000;
unsigned long previs_voltge_read;




void setup() {
  
pinMode (A0, INPUT);
pinMode (A1, INPUT);
pinMode (A2, INPUT);
pinMode (A3, INPUT_PULLUP);
pinMode (A4, OUTPUT);
pinMode (A5, OUTPUT);


pinMode (2, INPUT_PULLUP);
pinMode (3, INPUT_PULLUP);
pinMode (4, INPUT_PULLUP);
pinMode (5, INPUT_PULLUP);
pinMode (6, INPUT_PULLUP);
pinMode (7, INPUT_PULLUP);
pinMode (8, INPUT_PULLUP);
pinMode (9, INPUT_PULLUP);
pinMode (10, INPUT_PULLUP);
pinMode (11, INPUT_PULLUP);
pinMode (12, INPUT_PULLUP);
pinMode (13, INPUT_PULLUP);

Wire.begin ();
Serial.begin (9600);

//printing camandes
int random_number = random(0,200);


delay (3000);
}

void loop() {
  // senser reading timer
  unsigned long current_time = millis();

  // camra tilt
  cam_tilt = analogRead (camra_tillt);
  
  cam_tilt = map(cam_tilt,0,1023,0,180);
  
  Serial.print("camra_tillt = ");
  Serial.println(cam_tilt);
  
  // truster speed
  T_speed = analogRead (speed_controle);

  T_speed = map(T_speed,0,1023,0,180);

  Serial.print("speed_controle = ");
  Serial.println(T_speed);
  
 // left joystick 
  if (digitalRead(LJ_A) == LOW && digitalRead(LJ_D) == HIGH){
  T1 = back_;
  T3 = fowd_ ;
  }
  if (digitalRead(LJ_W) == LOW && digitalRead(LJ_S) == HIGH){
    T1 = fowd_;
    T3 = fowd_ ;
  }
  if (digitalRead(LJ_S) == LOW && digitalRead(LJ_W) == HIGH){
    T1 = back_;
    T3 = back_ ;
  }
  if (digitalRead(LJ_D) == LOW && digitalRead(LJ_A) == HIGH){
    T1 = fowd_;
    T3 = back_ ;
  }
  if(
     digitalRead(LJ_D) == HIGH
     &&
     digitalRead(LJ_S) == HIGH
     &&
     digitalRead(LJ_W) == HIGH
     &&
     digitalRead(LJ_A) == HIGH
  ){  
  T1 = stop_;
  T3 = stop_;
  }
  
  Serial.print("front_left_moter = ");
  Serial.println(T1);
  Serial.print("back_left_moter = ");
  Serial.println(T3);
  
  // center joystick
  if (digitalRead(CJ_A) == LOW && digitalRead(CJ_D) == HIGH){
  G_R_M = fowd_;
  }
  if (digitalRead(CJ_D) == LOW && digitalRead(CJ_A) == HIGH){
    G_R_M = back_ ;
  }
  if (
     digitalRead(CJ_D) == HIGH
     &&
     digitalRead(CJ_A) == HIGH
  ){
    G_R_M = stop_;
  }
  
  Serial.print("griper_moter = ");
  Serial.println(G_R_M);
  
  if (digitalRead(CJ_W) == LOW && digitalRead(CJ_S) == HIGH){
    L_V_M = fowd_;
  }
  if (digitalRead(CJ_S) == LOW && digitalRead(CJ_W) == HIGH){
    L_V_M = back_ ;
  }
  if( 
     digitalRead(CJ_S) == HIGH
     &&
     digitalRead(CJ_W) == HIGH   
  ){  
  L_V_M = stop_;
  }
  
  Serial.print("leveling_moter = ");
  Serial.println(L_V_M);
  
  // right joystick
  if (digitalRead(RJ_A) == LOW && digitalRead(LJ_D) == HIGH){
    T4 = back_;
    T6 = fowd_ ;
  }
  if (digitalRead(RJ_W) == LOW && digitalRead(LJ_S) == HIGH){
    T4 = fowd_;
    T6 = fowd_;
  }
  if (digitalRead(RJ_S) == LOW && digitalRead(RJ_W) == HIGH){
    T4 = back_;
    T6 = back_;
  }
  if (digitalRead(RJ_D) == LOW && digitalRead(RJ_A) == HIGH){
    T4 = fowd_;
    T6 = back_;
  }
  if(
     digitalRead(RJ_D) == HIGH
     &&
     digitalRead(RJ_S) == HIGH
     &&
     digitalRead(RJ_W) == HIGH
     &&
     digitalRead(RJ_A) == HIGH
  ){  
  T4 = stop_;
  T6 = stop_;
  }

  Serial.print("front_right_moter = ");
  Serial.println(T6);
  Serial.print("back_right_moter = ");
  Serial.println(T4);

  //lights
  
  light_state = digitalRead(light_swich);
  if (light_state == LOW){digitalWrite(lights_on_LED,HIGH);}
  if (light_state == HIGH){digitalWrite(lights_on_LED,LOW);}
 
  Serial.print("LIGHT state = ");
  Serial.println(light_state);
}

That's better.
In the Arduino IDE 2.0, you can right-click on the source code and then select "Format Document".

The pins with the 8 buttons are read 3 times each. The inputs could change between those reads, then your logic of the code gets disrupted.

You can collect all the data at the beginning of the loop() and put all the information in variables. Then the processing part (making decisions) is done in the middle of the loop() with the variables.
By using 'bool' variables, it even becomes better to read.
How cool does this look:

if (fruit and yellow)
  Serial.println("It is a banana");

Example with four cursor buttons:

void loop()
{
  bool up, left, down, right;

  int upValue = digitalRead( upPin);
  int leftValue = digitalRead( leftPin);
  int downValue = digitalRead( downPin);
  int rightValue = digitalRead( rightPin);

  if( upValue == LOW)
    up = true;
  else
    up = false;

 if( leftValue == LOW)
    left = true;
  else
    left = false;

 if( downValue == LOW)
    down = true;
  else
    down = false;

 if( rightValue == LOW)
    right = true;
  else
    right = false;

  if( up and left)
  {
    Serial.println( "Going to the upper-left");
  }
  else if( up and right)
  {
    Serial.println( "Going to the upper-right");
  }
  else
  {
    Serial.println( "I don't know where we are going");
  }
}

That was just for fun. But is gets better by writing it in a shorter way:

// if( upValue == LOW)
//    up = true;
//  else
//    up = false;
bool up = (upValue == LOW) ? true : false;

That is if-else-code without the word 'if' or 'else'.

This is also perfectly fine:

int LJ_A_value = digitalRead(LJ_A_pin);
int LJ_D_value = digitalRead(LJ_D_pin);
...
if ( LJ_A_value == LOW && LJ_D_value == HIGH)
{
  ...
}

Hi there. The arduino coding is going well, i haven't got much done as i can only work on the project in my free time.

The most recent problem with this project i have come across is how to send the video signal from the sub to the topside controller.

Im would if you have any ideas for how i can do this well using the lest number of wires possible as the transmission distance will be around 600 meters to 1.2km.

I don't need great video, just enough so i can see what is happening as i control the sub.

Is there any way to incorporate this video signal transmission into the arduinos operation or the rs485 modules witch are already in use.

Thanks for your time.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.