Attraction électrostatique entre charges électriques (loi de coulomb)

Description

Ce programme permet comme son nom l'indique de calculer la force électrostatique entre des charges électriques disposées dans un canevas et dont la position est changeable à volonté à l'aide de boutons prédisposés à cet effet.
Si vous avez vu ma précédente source qui consistait à calculer la force gravitationnelle vous comprendrez qu'il s'agit également du même type de programme que je présente ici mais que contrairement à son homologue il s'agit là de la loi de Coulomb comme objet d'étude de ce programme ce qui est totalement différent.

ATTENTION :

L'image fournie doit être enregistré au format .gif pour pouvoir être utilisé par le programme !!

Source / Exemple :


# -*- coding: cp1252 -*-
# Force d'intéraction électrique entre des charges

from Tkinter import *
from math import sqrt

# ---------- Déclaration de fonctions locales -----------------

def distance(x1, y1, x2, y2):                               #Cette fonction va nous permettre de calculer la distance entre les charges électriques
    d=sqrt((x2-x1)**2+(y2-y1)**2)
    return d

def forceE(ch1, ch2, di):                                         #Cette fonction va nous permettre de calculer la force exercée sur chaque charge électrique
    return (9*10^9)*((ch1*ch2)/di**2)

def echell(event):                                                      #Echelle de distance entre les charges
    global echelle
    echelle=float(entr4.get())*10e-10
    return echelle
  
#Les trois fonctions suivantes vont permettre de redéfinir la masse de chaque charge relatif au champ de saisi correspondant

def masse1(event):
    global q1
    f=0
    q1=float(entr1.get())
    di=distance(x[0],y[0],x[1],y[1])
    di2=distance(x[0],y[0],x[2],y[2])
    di=di*echelle
    di2=di2*echelle
    u12,v12=((x[1]-x[0])/di),((y[1]-y[0])/di)
    u13,v13=((x[2]-x[0])/di2),((y[2]-y[0])/di2)   
    f1=forceE(q1,q2,di)
    f2=forceE(q1,q3,di2)
    f=sqrt((f1*u12+f2*u13)**2+(f1*v12+f2*v13)**2)
    valDis.configure(text="Distance avec charge 2 = " +str(di)+" 10e-10m")
    valDis2.configure(text=" Distance avec charge 3 = " +str(di2)+" 10e-10m")
    valFor.configure(text="Force exercée sur la charge sélectionnée = " +str(f)+" C")
    valMass1.configure(text="Masse de la charge 1 = "+str(eval(entr1.get()))+" 10e-27Kg")
   

def masse2(event):
    global q2
    f=0
    q2=float(entr2.get())
    di=distance(x[1],y[1],x[0],y[0])
    di2=distance(x[1],y[1],x[2],y[2])
    di=di*echelle
    di2=di2*echelle
    u21,v21=((x[0]-x[1])/di),((y[0]-y[1])/di)
    u23,v23=((x[2]-x[1])/di2),((y[2]-y[1])/di2)
    f1=forceE(q2, q1, di)
    f2=forceE(q2,q3,di2)
    f=sqrt((f1*u21+f2*u23)**2+(f1*v21+f2*v23)**2)
    
    valDis.configure(text="Distance avec charge 1 = " +str(di)+" 10e-10m")
    valDis2.configure(text=" Distance avec charge 3 = " +str(di2)+" 10e-10m")
    valFor.configure(text="Force exercée sur la charge sélectionnée = " +str(f)+" C")
    valMass2.configure(text="Masse de la charge 2 = "+str(eval(entr2.get()))+" 10e-27Kg")
 
def masse3(event):
    global q3
    f=0
    q3=float(entr3.get())
    di=distance(x[2],y[2],x[0],y[0])
    di2=distance(x[2],y[2],x[1],y[1])
    di=di*echelle
    di2=di2*echelle
    u31,v31=((x[0]-x[2])/di),((y[0]-y[2])/di)
    u32,v32=((x[1]-x[2])/di2),((y[1]-y[2])/di2)   
    f1=forceE(q3,q1,di)
    f2=forceE(q3,q2,di2)
    f=sqrt((f1*u31+f2*u32)**2+(f1*v31+f2*v32)**2)

    valDis.configure(text="Distance avec charge 1 = " +str(di)+" 10e-10m")
    valDis2.configure(text=" Distance avec charge 2 = " +str(di2)+" 10e-10m")
    valFor.configure(text="Force exercée sur la charge sélectionnée = " +str(f)+" C")
    valMass3.configure(text="Masse de la charge 3 = "+str(eval(entr3.get()))+" 10e-27Kg")

#Les 3 fonctions ci-dessous permettent de redéfinir les coordonnées de chaque corps

def charge1(event):
    can.coords(charge[0],event.x+10,event.y+10,event.x-10,event.y-10)
    di=distance(event.x,event.y, x[1], y[1])
    di2=distance(event.x,event.y, x[2], y[2])
    di=di*echelle
    di2=di2*echelle
    u12,v12=((x[1]-x[0])/di),((y[1]-y[0])/di)
    u13,v13=((x[2]-x[0])/di2),((y[2]-y[0])/di2)   
    f1=forceE(q1,q2,di)
    f2=forceE(q1,q3,di2)
    f=sqrt((f1*u12+f2*u13)**2+(f1*v12+f2*v13)**2)
    valDis.configure(text="Distance avec charge 2 = " +str(di)+" 10e-10m")
    valDis2.configure(text=" Distance avec charge 3 = " +str(di2)+" 10e-10m")
    valFor.configure(text="Force exercé sur la charge 1 = " +str(f)+" C")
    x[0],y[0]=event.x,event.y
 
def charge2(event):
    can.coords(charge[1],event.x+10,event.y+10,event.x-10,event.y-10)
    di=distance(event.x, event.y, x[0], y[0])
    di2=distance(event.x, event.y, x[2], y[2])
    di=di*echelle
    di2=di2*echelle
    u21,v21=(x[0]-x[1])/di,(y[0]-y[1])/di
    u23,v23=(x[2]-x[1])/di2,(y[2]-y[1])/di2
    f1=forceE(q2, q1, di)
    f2=forceE(q2,q3,di2)
    f=sqrt((f1*u21+f2*u23)**2+(f1*v21+f2*v23)**2)
    valDis.configure(text="Distance avec charge 1 = " +str(di)+" 10e-10m")
    valDis2.configure(text="Distance avec charge 3 = " +str(di2)+" 10e-10m")
    valFor.configure(text="Force exercé sur charge 2= " +str(f)+" C")
    x[1],y[1]=event.x,event.y

def charge3(event):
    can.coords(charge[2],event.x+10,event.y+10,event.x-10,event.y-10)
    di=distance(event.x, event.y, x[0], y[0])
    di2=distance(event.x, event.y, x[1], y[1])
    di=di*echelle
    di2=di2*echelle
    u31,v31=((x[0]-x[2])/di),((y[0]-y[2])/di)
    u32,v32=((x[1]-x[2])/di2),((y[1]-y[2])/di2)   
    f1=forceE(q3,q1,di)
    f2=forceE(q3,q2,di2)
    f=sqrt((f1*u31+f2*u32)**2+(f1*v31+f2*v32)**2)
    valDis.configure(text="Distance avec charge 1 = " +str(di)+" 10e-10m")
    valDis2.configure(text="Distance avec charge 2 = " +str(di2)+" 10e-10m")
    valFor.configure(text="Force exercée sur charge 3= " +str(f)+" C")
    x[2],y[2]=event.x,event.y

    
# Les 3 fonctions ci-dessous vont permettre d'obtenir l'état de la distance et de la force
# exercée pour chacun des corps, elles vont également nous permettre de replacer
# chacun des corps dans le canevas où bon nous semble en appelant les 3 fonctions ci-dessus.

def charge_1():
    can.bind("<Button-1>" ,charge1)
    di=distance(x[0],y[0],x[1],y[1])
    di2=distance(x[0],y[0],x[2],y[2])
    di=di*echelle
    di2=di2*echelle
    u12,v12=((x[1]-x[0])/di),((y[1]-y[0])/di)                #Coordonées du vecteur de force entre charge 1 et charge 2       
    u13,v13=((x[2]-x[0])/di2),((y[2]-y[0])/di2)            #Coordonnées du vecteur de force entre charge 2 et charge 3
    f1=forceE(q1,q2,di)
    f2=forceE(q1,q3,di2)
    f=sqrt((f1*u12+f2*u13)**2+(f1*v12+f2*v13)**2)
    valDis.configure(text="Distance avec charge 2 = " +str(di)+" 10e-10m")
    valDis2.configure(text=" Distance avec charge 3 = " +str(di2)+" 10e-10m")
    valFor.configure(text="Force exercée sur la charge sélectionnée = " +str(f)+" C")
    Label(fra1,text="Charge 1 sélectionnée ", fg='light blue').grid(row=0, column=5)
    Label(fra1,text="Cliquez n'importe où dans le cadre afin de redéfinir la position de la charge sélectionnée").grid(row=0,column=6)
  
    

def charge_2():
    can.bind("<Button-1>",charge2)
    di=distance(x[1],y[1],x[0],y[0])
    di2=distance(x[1],y[1],x[2],y[2])
    di=di*echelle
    di2=di2*echelle
    u21,v21=((x[0]-x[1])/di),((y[0]-y[1])/di)
    u23,v23=((x[2]-x[1])/di2),((y[2]-y[1])/di2)   
    f1=forceE(q2, q1, di)
    f2=forceE(q2,q3,di)
    f=sqrt((f1*u21+f2*u23)**2+(f1*v21+f2*v23)**2)
    valDis.configure(text="Distance avec charge 1 = " +str(di)+" 10e-10m")
    valDis2.configure(text="Distance avec charge 3 = " +str(di2)+" 10e-10m")
    valFor.configure(text="Force exercée sur la charge sélectionnée = " +str(f)+" C")
    Label(fra1, text="Charge 2 sélectionnée ", fg='light green').grid(row=0,column=5)
    Label(fra1,text="Cliquez n'importe où dans le cadre afin de redéfinir la position de la charge sélectionnée").grid(row=0,column=6)
   

def charge_3():
    can.bind("<Button-1>",charge3)
    di=distance(x[2],y[2],x[0],y[0])
    di2=distance(x[2],y[2],x[1],y[1])
    di=di*echelle
    di2=di2*echelle
    u31,v31=((x[0]-x[2])/di),((y[0]-y[2])/di)
    u32,v32=((x[1]-x[2])/di2),((y[1]-y[2])/di2)   
    f1=forceE(q3,q1,di)
    f2=forceE(q3,q2,di2)
    f=sqrt((f1*u31+f2*u32)**2+(f1*v31+f2*v32)**2)
 
    valDis.configure(text="Distance avec charge 1 = " +str(di)+" 10e-10m")
    valDis2.configure(text="Distance avec charge 2 = " +str(di2)+" 10e-10m")
    valFor.configure(text="Force exercée sur la charge sélectionnée = " +str(f)+" C")
    Label(fra1, text="Charge 3 sélectionnée ", fg='yellow').grid(row=0,column=5)
    Label(fra1,text="Cliquez n'importe où dans le cadre afin de redéfinir la position de la charge sélectionnée").grid(row=0,column=6)
 
# Les 3 fonctions ci-dessous vont nous permettre de définir le signe de chaque charge ainsi que l'état de la force qui résulte entre chacune des charges

def Signe_charge1(event):
    global q1
    global Signe_q1
    global Signe_q2
    Signe_q1=""
    Etat_force=""
    if entr5.get()=="positif":
        Signe_q1="positif"
    elif entr5.get()=="negatif":
        Signe_q1="negatif"
    else:
        Signe_q1="Erreur de saisi"

    if Signe_q2=="positif" or Signe_q2=="negatif":          #Dans le cas où la variable contient la chaine "positif" ou "negatif" on continue sinon on retourne une erreur de saisie
        if Signe_q1==Signe_q2:
            Etat_force="Répulsive"
        elif Signe_q1=="positif" and Signe_q2=="negatif" or Signe_q1=="negatif" and Signe_q2=="positif":
            Etat_force="Attractive"
        else:
            Etat_force="Erreur de saisi"
    else:
        Etat_force="Erreur de saisi"

    if Signe_q3=="positif" or Signe_q3=="negatif":
        if Signe_q3==Signe_q1:
            Etat_force="Répulsive"
        elif Signe_q3=="positif" and Signe_q1=="negatif" or Signe_q3=="negatif" and Signe_q1=="positif":
            Etat_force="Attractive"
        else:
            Etat_force="Erreur de saisi"
    else:
        Etat_force="Erreur de saisi"
        
    di=distance(x[0],y[0], x[1], y[1])
    di2=distance(x[0],y[0], x[2], y[2])
    di=di*echelle
    di2=di2*echelle
    u12,v12=((x[1]-x[0])/di),((y[1]-y[0])/di)
    u13,v13=((x[2]-x[0])/di2),((y[2]-y[0])/di2)   
    f1=forceE(q1,q2,di)
    f2=forceE(q1,q3,di2)
    f=sqrt((f1*u12+f2*u13)**2+(f1*v12+f2*v13)**2)
    valDis.configure(text="Distance avec charge 2 = " +str(di)+" 10e-10m")
    valDis2.configure(text=" Distance avec charge 3 = " +str(di2)+" 10e-10m")
    valFor.configure(text="Force exercé sur la charge 1 = " +str(f)+" C")
    statusSigne_q1.configure(text="Signe de la charge 1 = "+Signe_q1)
    statusForce_q1_q2.configure(text="Etat de la force entre charge 1 et charge 2 : "+Etat_force)
    statusForce_q1_q3.configure(text="Etat de la force entre charge 3 et charge 1 : "+Etat_force)
 

def Signe_charge2(event):
    global q2
    global Signe_q2
    Signe_q2=""
    Etat_force=""
    Etat_force2=""
    if entr6.get()=="positif":
        Signe_q2="positif"
    elif entr6.get()=="negatif":
        Signe_q2="negatif"
    else:
        Signe_q2="Erreur de saisi"

    if Signe_q2=="positif" or Signe_q2=="negatif":
        if Signe_q2==Signe_q1:
            Etat_force="Répulsive"
        elif Signe_q2=="positif" and Signe_q1=="negatif" or Signe_q2=="negatif" and Signe_q1=="positif":
            Etat_force="Attractive"
        else:
            Etat_force="Erreur de saisi"
    else:
        Etat_force="Erreur de saisi"
    if Signe_q3=="positif" or Signe_q3=="negatif":
        if Signe_q3==Signe_q2:
            Etat_force2="Répulsive"
        elif Signe_q3=="positif" and Signe_q2=="negatif" or Signe_q3=="negatif" and Signe_q2=="positif":
            Etat_force2="Attractive"
        else:
            Etat_force2="Erreur de saisi"
    else:
        Etat_force2="Erreur de saisi"
        
    di=distance(x[1],y[1], x[0], y[0])
    di2=distance(x[1],y[1], x[2], y[2])
    di=di*echelle
    di2=di2*echelle
    u21,v21=(x[0]-x[1])/di,(y[0]-y[1])/di
    u23,v23=(x[2]-x[1])/di2,(y[2]-y[1])/di2
    f1=forceE(q2, q1, di)
    f2=forceE(q2,q3,di2)
    f=sqrt((f1*u21+f2*u23)**2+(f1*v21+f2*v23)**2)
    valDis.configure(text="Distance avec charge 1 = " +str(di)+" 10e-10m")
    valDis2.configure(text="Distance avec charge 3 = " +str(di2)+" 10e-10m")
    valFor.configure(text="Force exercé sur charge 2 = " +str(f)+" C")
    statusSigne_q2.configure(text="Signe de la charge 2 = "+Signe_q2)
    statusForce_q1_q2.configure(text="Etat de la force entre charge 2 et charge 1 : "+Etat_force)
    statusForce_q2_q3.configure(text="Etat de la force entre charge 2 et charge 3 : "+Etat_force2)
   

def Signe_charge3(event):
    global q3
    global Signe_q3
    Signe_q3=""
    Etat_force=""
    Etat_force2=""
    if entr7.get()=="positif":
        Signe_q3="positif"
    elif entr7.get()=="negatif":
        Signe_q3="negatif"
    else:
        Signe_q3="Erreur de saisi"

    if Signe_q3=="positif" or Signe_q3=="negatif":
        if Signe_q3==Signe_q1:
            Etat_force="Répulsive"
        elif Signe_q3=="positif" and Signe_q1=="negatif" or Signe_q3=="negatif" and Signe_q1=="positif":
            Etat_force="Attractive"
        else:
            Etat_force="Erreur de saisi"
    else:
        Etat_force="Erreur de saisi"

    if Signe_q3=="positif" or Signe_q3=="negatif":
        if Signe_q3==Signe_q2:
            Etat_force2="Répulsive"
        elif Signe_q3=="positif" and Signe_q2=="negatif" or Signe_q3=="negatif" and Signe_q2=="positif":
            Etat_force2="Attractive"
        else:
            Etat_force2="Erreur de saisi"
    else:
        Etat_force2="Erreur de saisi"
        
    di=distance(x[1],y[1], x[0], y[0])
    di2=distance(x[1],y[1], x[2], y[2])
    di=di*echelle
    di2=di2*echelle
    u31,v31=((x[0]-x[2])/di),((y[0]-y[2])/di)
    u32,v32=((x[1]-x[2])/di2),((y[1]-y[2])/di2)   
    f1=forceE(q3,q1,di)
    f2=forceE(q3,q2,di2)
    f=sqrt((f1*u31+f2*u32)**2+(f1*v31+f2*v32)**2)
    valDis.configure(text="Distance avec charge 1 = " +str(di)+" 10e-10m")
    valDis2.configure(text="Distance avec charge 2 = " +str(di2)+" 10e-10m")
    valFor.configure(text="Force exercée sur charge 3 = " +str(f)+" C")
    statusSigne_q3.configure(text="Signe de la charge 3 = "+Signe_q3)
    statusForce_q1_q3.configure(text="Etat de la force entre charge 3 et charge 1 : "+Etat_force)
    statusForce_q2_q3.configure(text="Etat de la force entre charge 2 et charge 3 : "+Etat_force2)

# ------------- Programme principal ------------------

global q1,q2,q3 
                                               

q1=0                                                            #Masse des charges                                     
q2=0
q3=0
charge=[0]*3

x=[50., 50.,50.]                                  # Coordonnées des charges
y=[100., 150.,200.]

global echelle
echelle=10e-10

Signe_q1,Signe_q2,Signe_q3="","",""

avertissement=Tk()
avertissement.title("Avertissement")
Label(avertissement,text="Attention !! Toujours appuyer sur entrée après avoir effectuer votre saisie afin de considérer le nouveau changement !",fg='red').pack()
Button(avertissement,text="OK",command=avertissement.destroy).pack()
avertissement.mainloop()

fen=Tk()

fen.title('Force d\'attraction électrique ( LOI DE COULOMB )')            #Titre de la fenêtre

valM1=Label(fen, text="Masse de la charge 1 ( 10e-27Kg ) :")                        #Affichage de la masse de chacune des charges
valM1.grid(row=3, column=1,sticky=E)

#Champs de saisie permettant de redéfinir la masse de chacune des charges

entr1=Entry(fen)
entr1.grid(row=3,column=2, sticky=W)
entr1.bind("<Return>",masse1)

valM2=Label(fen, text="Masse de la charge 2 ( 10e-27Kg ) :")
valM2.grid(row=4, column=1, sticky=E)

entr2=Entry(fen)
entr2.grid(row=4,column=2,sticky=N)
entr2.bind("<Return>",masse2)

valM3=Label(fen,text="Masse de la charge 3 ( 10e-27Kg ) :")
valM3.grid(row=5, column=1,sticky=E)

entr3=Entry(fen)
entr3.grid(row=5,column=2,sticky=N)
entr3.bind("<Return>",masse3)

#Champ de saisi permettant de rédéfinir l'échelle de distance entre les charges

echelleDis=Label(fen, text="(A saisir en premier !!) Echelle de la distance (1 = 10e-10m) :")
echelleDis.grid(row=2,column=1,sticky=E)

entr4=Entry(fen)
entr4.grid(row=2,column=2,sticky=W)
entr4.bind("<Return>",echell)

#Champ permettant de définir le signe de chaque charge

Label(fen,text="Signe de la charge 1 ( taper \"positif\" ou \"negatif\") :").grid(row=6,column=1,sticky=E)
entr5=Entry(fen)
entr5.grid(row=6,column=2,sticky=N)
entr5.bind("<Return>",Signe_charge1)

Label(fen,text="Signe de la charge 2 ( taper \"positif\" ou \"negatif\") :").grid(row=7,column=1,sticky=E)
entr6=Entry(fen)
entr6.grid(row=7,column=2,sticky=N)
entr6.bind("<Return>",Signe_charge2)

Label(fen,text="Signe de la charge 3 ( taper \"positif\" ou \"negatif\") :").grid(row=8,column=1,sticky=E)
entr7=Entry(fen)
entr7.grid(row=8,column=2,sticky=N)
entr7.bind("<Return>",Signe_charge3)

valDis=Label(fen)                        
valDis.grid(row=3, column=0)

valDis2=Label(fen, text="Veuillez sélectionner une charge à l'aide des 3 boutons se réferrant aux charges")
valDis2.grid(row=2,column=0,sticky=N)

valFor=Label(fen)
valFor.grid(row=4, column=0)

statusSigne_q1=Label(fen)
statusSigne_q1.grid(row=8,column=0)

statusSigne_q2=Label(fen)
statusSigne_q2.grid(row=9,column=0)

statusSigne_q3=Label(fen)
statusSigne_q3.grid(row=10,column=0)

statusForce_q1_q2=Label(fen)
statusForce_q1_q2.grid(row=11,column=0)

statusForce_q1_q3=Label(fen)
statusForce_q1_q3.grid(row=12,column=0)

statusForce_q2_q3=Label(fen)
statusForce_q2_q3.grid(row=13,column=0)

valMass1=Label(fen)
valMass1.grid(row=5,column=0)
valMass2=Label(fen)
valMass2.grid(row=6,column=0)
valMass3=Label(fen)
valMass3.grid(row=7,column=0)

#Création de la surface coloré sur laquelle les charges y seront plaçées et replaçées

can=Canvas(fen, bg="light yellow", width=700, height=450)
can.grid(row=1, column=0)
charge[0]=can.create_oval(x[0]-10,y[0]-10, x[0]+10, y[0]+10, fill="light blue", width=2)                 # Création des charges sous forme visuelle
charge[1]=can.create_oval(x[1]-10, y[1]-10, x[1]+10, y[1]+10, fill="light green", width=2)
charge[2]=can.create_oval(x[2]-10,y[2]-10,x[2]+10,y[2]+10,fill="yellow",width=2)

fra1=Frame(fen)
fra1.grid(row=0, column=0, sticky=W)

can1=Canvas(fen,width=119,height=140,bg='light blue')
can1.grid(row=1,column=1,sticky=NW)
photo=PhotoImage(file='coulomb.gif')
can1.create_image(59.50,70,image=photo)

Button(fra1, text="charge1", fg='light blue', command=charge_1).grid(row=0,column=1,sticky=W,padx=1)                     #Boutons permettant de sélectionner une charge
Button(fra1,text="charge2",fg='light green',command=charge_2).grid(row=0,column=2,sticky=E,padx=1)
Button(fra1,text="charge3",fg="yellow",command=charge_3).grid(row=0,column=3,sticky=E,padx=1)

Button(fra1,text="Quitter",command=fen.destroy).grid(row=0,column=4,pady=5)

fen.mainloop()              #Demarrage

Conclusion :


J'ai donc repris quelques éléments du programme précédent en apportant toutefois quelques retouches.
En espérant que le programme soit bien pensé et qu'il ne comporte pas trop d'erreur car après tout je ne suis qu'un débutant ^^ de plus la physique n'est pas trop mon fort n'est ce pas HCD ^^

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.