diff --git a/charge/charge.c b/charge/charge.c
index 42e91b6290dcac17b238589c63f75aa87a3087d7..2158dfdc2b20123b2103dcc7b6e462ba151edaf3 100644
--- a/charge/charge.c
+++ b/charge/charge.c
@@ -72,5 +72,46 @@ charge_t charge_create(double q, vec2 pos) {
 }
 
 double random_charge_q(bool positive) {
-    return rand_one() * (positive ? 1 : -1);
+    return (rand() % 100) * (positive ? 1 : -1);
+}
+
+vec2 electristatic_force(charge_t a, charge_t b) {
+    vec2 rab = vec2_sub(b.pos, a.pos);
+    vec2 res = vec2_mul(
+        rab, K * (((a.q * 10e-6) * (b.q * 10e-6)) / pow(vec2_norm(rab), 2)));
+
+    printf("COEF: %.25f\n", (a.q * 10e-6) * (b.q * 10e-6));
+    return res;
+}
+
+vec2 resulting_electrostatic_force(charge_t *charges, int num_charges,
+                                   charge_t a) {
+    vec2 resulting = vec2_create_zero();
+
+    for (int i = 0; i < num_charges; i++) {
+        // Very unlickly to have two charges with the exact same charge
+        if (charges[i].q == a.q)
+            continue;
+
+        vec2 ef = electristatic_force(a, charges[i]);
+        resulting = vec2_add(resulting, ef);
+    }
+
+    return resulting;
+}
+
+void update_charge_pos(charge_t *charges, int num_charges, charge_t *a) {
+    vec2 resulting = resulting_electrostatic_force(charges, num_charges, *a);
+    a->pos = vec2_add(a->pos, resulting);
+}
+
+void update_simulation(charge_t *charges, int num_charges) {
+    for (int i = 0; i < num_charges; i++) {
+        vec2 resulting =
+            resulting_electrostatic_force(charges, num_charges, charges[i]);
+        printf("RES: %.19f\n", vec2_norm(resulting));
+        charges[i].pos = vec2_add(charges[i].pos, resulting);
+    }
+
+    printf("%.19f, %.19f\n", charges[0].pos.x, charges[0].pos.x);
 }
\ No newline at end of file
diff --git a/charge/charge.h b/charge/charge.h
index 097fe21859857c0fa949941563d4d0b62aa85d35..57fc6687f5111c5b5e6d10e1001fcdf9a975666a 100644
--- a/charge/charge.h
+++ b/charge/charge.h
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 
 #define K 8.988e9
+#define ELEMENTARY_CHARGE 1.602176634e-19
 #define CHARGE_RADIUS 10
 #define EPS 0.015
 #define UNIV_MIN_X 0
@@ -118,4 +119,42 @@ charge_t charge_create(double q, vec2 pos);
  */
 double random_charge_q(bool positive);
 
+/**
+ * @brief Compute the electrostatic force between two charges
+ *
+ * @param a
+ * @param b
+ * @return vec2
+ */
+vec2 electristatic_force(charge_t a, charge_t b);
+
+/**
+ * @brief Compute the resulting electrostatic force
+ *
+ * @param charges
+ * @param num_charges
+ * @param a
+ * @return vec2
+ */
+vec2 resulting_electrostatic_force(charge_t *charges, int num_charges,
+                                   charge_t a);
+
+/**
+ * @brief Update the pos of the given charge based on the resulting
+ * electrostatic force
+ *
+ * @param charges
+ * @param num_charges
+ * @param a
+ */
+void update_charge_pos(charge_t *charges, int num_charges, charge_t *a);
+
+/**
+ * @brief Update the whole simulation
+ *
+ * @param charges
+ * @param num_charges
+ */
+void update_simulation(charge_t *charges, int num_charges);
+
 #endif
\ No newline at end of file
diff --git a/draw/draw.c b/draw/draw.c
index e178166fbee66f348d743a45036523ef11c9e2a3..021825507bdf84498ec63dcfde193fdc065f6ab8 100644
--- a/draw/draw.c
+++ b/draw/draw.c
@@ -202,7 +202,7 @@ void draw_charges(charge_t *charges, int num_charges, int w, int h) {
         draw_circle(chCoord, CHARGE_RADIUS);
 
         char charge_str[8];
-        snprintf(charge_str, 8, "%.4f", charges[i].q);
+        snprintf(charge_str, 8, "%.0f", charges[i].q);
         vec2 text_pos = vec2_create(chCoord.x, chCoord.y + CHARGE_RADIUS + 4);
         draw_textbox(text_pos, charge_str);
     }
diff --git a/main.c b/main.c
index ae82fc98583f96190a75a6afb2faae1c5aef18fa..f653e82de46a0ae8f6edd717609faea0f919f9ab 100644
--- a/main.c
+++ b/main.c
@@ -29,6 +29,9 @@
 #define UNUSED(x) x
 #endif
 
+#define ONE_SECOND_IN_MILLISECONDS 1000
+#define REFRESH_RATE 200
+
 #define WINDOW_WIDTH 800
 #define WINDOW_HEIGHT 800
 #define NB_CHARGES 5
@@ -42,11 +45,24 @@ int charge_count = NB_CHARGES;
 vec2 starting_points[NB_POINTS];
 vec2 default_charges_pos[MAXIMUM_CHARGES];
 double default_charges[MAXIMUM_CHARGES];
+charge_t *charges;
 
-bool toggle_lines_view = true;
+bool toggle_lines_view = false;
 bool toggle_vector_view = false;
 bool toggle_heatmap_view = false;
 
+void update() { update_simulation(charges, charge_count); };
+
+void update_timer() {
+    update();
+    glutTimerFunc(ONE_SECOND_IN_MILLISECONDS / REFRESH_RATE, update_timer, 0);
+}
+
+void draw_timer() {
+    glutPostRedisplay();
+    glutTimerFunc(ONE_SECOND_IN_MILLISECONDS / REFRESH_RATE, draw_timer, 0);
+}
+
 /**
  * @brief Generate a grid of points
  *
@@ -72,11 +88,6 @@ void display() {
     glClearColor(0, 0, 0, 1);
     glClear(GL_COLOR_BUFFER_BIT);
 
-    // Generate all the charges
-    charge_t charges[charge_count];
-    for (int i = 0; i < charge_count; i++)
-        charges[i] = charge_create(default_charges[i], default_charges_pos[i]);
-
     if (toggle_heatmap_view)
         draw_heatmap(charges, charge_count, WINDOW_WIDTH, WINDOW_HEIGHT);
 
@@ -110,6 +121,7 @@ void handle_mouse_input(int button, int state, int x, int y) {
     if (state == GLUT_UP)
         return;
 
+    // Define new charges attributes
     if (button == GLUT_LEFT_BUTTON || button == GLUT_RIGHT_BUTTON) {
         charge_count += 1;
         default_charges_pos[charge_count - 1] =
@@ -122,6 +134,13 @@ void handle_mouse_input(int button, int state, int x, int y) {
     if (button == GLUT_RIGHT_BUTTON)
         default_charges[charge_count - 1] = random_charge_q(false);
 
+    // Realloc charge array when a new one is added
+    charges = realloc(charges, sizeof(charge_t) * charge_count);
+
+    // Redefine all charges infos
+    for (int i = 0; i < charge_count; i++)
+        charges[i] = charge_create(default_charges[i], default_charges_pos[i]);
+
     glutPostRedisplay();
 }
 
@@ -158,12 +177,18 @@ void keyboard(unsigned char key, int UNUSED(x), int UNUSED(y)) {
 int main(int argc, char **argv) {
     srand(time(NULL));
 
+    charges = malloc(sizeof(charge_t) * charge_count);
+
     // Generate all default charges
     for (int i = 0; i < charge_count; i++) {
         default_charges[i] = random_charge_q((bool)(rand() % 2 == 0));
         default_charges_pos[i] = vec2_create(rand_one(), rand_one());
     }
 
+    // Init charges
+    for (int i = 0; i < charge_count; i++)
+        charges[i] = charge_create(default_charges[i], default_charges_pos[i]);
+
     // Generate all field lines starting points
     generate_points(starting_points);
 
@@ -184,9 +209,14 @@ int main(int argc, char **argv) {
     glutMouseFunc(handle_mouse_input);
     glutKeyboardFunc(keyboard);
 
+    // glutTimerFunc(ONE_SECOND_IN_MILLISECONDS / REFRESH_RATE, update_timer,
+    // 0); glutTimerFunc(ONE_SECOND_IN_MILLISECONDS / REFRESH_RATE, draw_timer,
+    // 0);
+
     glutMainLoop();
 
     // Object destroy
     glutDestroyWindow(window);
+    free(charges);
     return EXIT_SUCCESS;
 }
\ No newline at end of file