Dva progrmy a I2C

Odpovědět
haas

Dva progrmy a I2C

Příspěvek od haas »

Dobrý den.
Mám robota, kde jsou dvě Atmegy328 propojené sběrnicí.Master provádí hlavní program a po sběrnici se dotazuje na slave jaké jsou vstupní data na senzorech.Slave provede měření a odešle vše zpět.Pokud používám pouze jeden program( vyhýbání se překážkám pomocí ultrazvuku nebo sledování čáry) tak vše funguje.Jenže nyní jsou v mastru nahrány programy jak na čáru tak na ultrazvuk a po spuštění robata si pomocí lcd a tlačítka vyberu program, který chci spustit.Master by měl načíst číslo programu a pak ho po sběrnici poslat na slave.Slave by pak měl na dotaz jaký je stav na vstupech senzorů provést buď měření vzdálenosti nebo zjistit polohu čáry.

Zde je problém.Master funguje jak má, ale např.při měření ultrazvukem se žádné měření neprovede.Slave asi vůbec neví co má dělat.Podle mě jsem asi nešťasně zvoli způsob předávání čísla programu z master na slave.Nyní je to tak, že slave očekává příjem dat příkazem Wire.onReceive(vyber_programu) v okamžiku zahájení komunikace přijme data obsahující číslo programu a pak by se měla komunikace provádět pomocí příkazu Wire.onRequest().

Jde o to, aby slave po nastavení čílsa programu provedl na žádost o měření pouze smyčku pro měření vzálenosti ultrzvukem nebo pouze přečetl data ze senzoru čáry a odeslal je na mastr.Nastavení by se mělo provést ve smyčce loop(), kde podle přijatého čísla programu nastaví další obsluhu I2C.

Můžete mi prosím poradit?




Zde je kod.

SLAVE

//i2c Slave
#include <Wire.h>
const int pingPin = 6;
long duration, cm;
int leveKraj;
int leveStred;
int praveStred;
int praveKraj;
char data_master=0;

void setup() {
pinMode(7,INPUT);
pinMode(8,INPUT);
pinMode(9,INPUT);
pinMode(10,INPUT);
Wire.begin(5);
Wire.onReceive(vyber_programu);
}

void loop() {
if(data_master==1) {
Wire.onRequest(ultrazvuk_mereni);
}
if(data_master==2) {
Wire.onRequest(cara_mereni);
}
delay(50);
}


void vyber_programu(int howMany) {

while(Wire.available()) {
char data_master=Wire.read();
}
loop();
}




void ultrazvuk_mereni() {

pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);

pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);

pinMode(pingPin,OUTPUT);
delay(10);
cm = microsecondsToCentimeters(duration);

Wire.write(cm);
loop();
}

long microsecondsToCentimeters(long microseconds){
return microseconds / 29 / 2;
}






void cara_mereni() {
leveKraj=digitalRead(7);
leveStred=digitalRead(8);
praveStred=digitalRead(9);
praveKraj=digitalRead(10);
if(leveKraj&&leveStred&&praveStred&&praveKraj==LOW) {
Wire.write(3);
}

if(leveStred==LOW) {
Wire.write(2);
}

if(praveStred==LOW) {
Wire.write(1);
}

if(praveStred&&leveStred==LOW) {
Wire.write(0);
}
loop();
}





ÚVODNÍ ČÁST Z MASTRU

//i2c Master(UNO)
#include <Wire.h>
#include <LiquidCrystal.h>
#include<Servo.h>
LiquidCrystal lcd(11, 12, 10, 9, 8, 7);
Servo myservo;
int cislo_programu=0;


void setup() {

myservo.attach(2);
lcd.begin(16, 2);
Wire.begin();
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(13,INPUT);
}

void loop() {
lcd.clear();
lcd.print("ZVOLTE PROGRAM");
delay(20);
if(digitalRead(13)==LOW) {
cislo_programu=cislo_programu+1;
lcd.clear();
lcd.print("ULTRAZVUK");
delay(2000);

if(digitalRead(13)==HIGH) {
Wire.beginTransmission(5);
Wire.write(cislo_programu);
Wire.endTransmission();
delay(2000);
ultrazvuk();
}

cislo_programu=cislo_programu+1;
lcd.clear();
lcd.print("CARA");
delay(2000);

if(digitalRead(13)==HIGH) {
Wire.beginTransmission(5);
Wire.write(cislo_programu);
Wire.endTransmission();
delay(2000);
cara();
}

cislo_programu=0;
delay(100);
loop();

}
}



Dále je už program pro zpracování přijatých dat ze slave.
haas

Re: Dva progrmy a I2C

Příspěvek od haas »

Ještě bych se chtěl zeptat na vaše zkušenosti s odprásknutými jednočipy.Když chci změnit program, tak musím vytáhnout jednočip z robota a vrazit ho desky arduina, pak ho zase vrátím zpět.Už se zase stalo, že po vrácení mikroprocesoru do robota se začal chovat divně a pak se třeba resetuje.Postupným zkoušením jsem zjistil, že je v pytli některý ze vstupů.Jenže pokud ten špatný vstup nepoužívám tak vše krásně funguje, dokonce i při programování nenastává žádná chyba.

Jak je možné že vždy odpálím jen určité vstupy a ne celý mikroprocesor?Je to způsobeno statickou elektřinou?(pokaždé se snažím vybít o kolík v zásuvce nebo topení)
Nebo mikroprocrsorům vadí samotné vytahování z patic?Jaké máte zkušenosti s tímhle?
Používám atmegu328.
Můj robot je nějak prokletý.Po 3 měsících se pořád vyskytují problémy.Teď jsem s hrůzou zjistil že napětí pro logiku se pohybuje kolem 5.5V což dříve nebylo............
no prostě hrůza :-)
AlesH
Příspěvky: 323
Registrován: 25 úno 2013, 09:18

Re: Dva progrmy a I2C

Příspěvek od AlesH »

Ahoj. Na první zkouknutí Tvého programu mi není jasné, proč voláš "loop()" z různých podprogramů (a v masteru snad dokonce přímo z loop(), tedy rekurzivně)? To mi připadá zbytečné a osobně bych všechna tato volání vyhodil. Předpokládám, že podporogramy se po dokončení vrátí tam, odkud byly zavolány, takže tvrdě psát na konec podprogramů "loop()" je podle mne chyba.

Ovšem nedokážu s jistotou říct, jestli vyhození volání "loop()" pomůže rozchodit celý Tvůj program, protože to nechci celé zkoušet na svém zařízení. Je pro mne také docela těžké zkoumat cizí program bez komentářů a bez rozumného formátování. Používej pro kód, prosím, alespoň zdejší tag "code". Obvykle se ten kód pak čte lépe a rychleji.

P.S.: Mikroprocesory z patic nevytahuju (používám zatím jen celé Arduino), takže s tím žádné zkušenosti nemám.
hubacekp
Příspěvky: 259
Registrován: 24 úno 2013, 13:40

Re: Dva progrmy a I2C

Příspěvek od hubacekp »

Ahoj, mám pár komentářů a myslím, že by sis měl nejdříve vyladit co nejmenší program pro demonstraci funkce master - slave. Jak a čím data ze slave čteš v masteru? víš zda adresa slave opravdu odpovídá té, kterou posíláš ve Wire.beginTransmission(5)?

SLAVE
v úvodu definujš: char data_master=0;
v loop() máš if(data_master==1) jako kdyby data_master byl int
ve vyber_programu(int howMany) máš char data_master=Wire.read() čímž definujete úplně novou proměnnou místo přiřazení hodnoty do proměnné definované v úvodu
volání loop() vyhoď jak již bylo řečeno
ve void ultrazvuk_mereni() definuješ několikrát různé pinMode() což moc nechápu proč to není v setup()

postrádám tam čtení dat, která slave pošle na master. Zde je příklad z http://arduino.cc/en/Reference/WireRead#.UwHEI6JrgWg

Kód: Vybrat vše

/*Description
Reads a byte that was transmitted from a slave device to a master after a call to requestFrom() or was transmitted from a master to a slave. read() inherits from the Stream utility class.*/
#include <Wire.h>

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
}

void loop()
{
  Wire.requestFrom(2, 6);    // request 6 bytes from slave device #2
  while(Wire.available())    // slave may send less than requested
  { 
    char c = Wire.read();    // receive a byte as character
    Serial.print(c);         // print the character
  }
  delay(500);
}
haas

Re: Dva progrmy a I2C

Příspěvek od haas »

To volání loop sem tam dal spíš preventivně.
To přepínání vstupu na výstup pinMode musí být v programu, protože používám srf 05 v třípinovém režimu.Tedy pužívám jeden pin jako výstup pro vyslání budícího signálu pro měření a pak zpětně čtu délku pulsu rovnající se vzdálenosti překážky.
Odeslání dat z master na slave je Wire.write(cm); nebo Wire.write(1)..

On ten program už funguje, jen jsem ho musel upravit

Kód: Vybrat vše

//i2c Slave(LEONARDO)
#include <Wire.h>
const int pingPin = 6;
long duration, cm;
int leveKraj;
int leveStred;
int praveStred;
int praveKraj;
int a=0;

void setup()  { 
  pinMode(7,INPUT);
  pinMode(8,INPUT);
  pinMode(9,INPUT);
  pinMode(10,INPUT);
  Wire.begin(5);
  
  Wire.onReceive(vyber_programu);
}

void loop()
{
  delay(50);
}


void vyber_programu(int howMany)   {
  
   while(Wire.available())   {
      char data_master=Wire.read();
   if(data_master==1)   {
      Wire.onRequest(ultrazvuk_mereni);
      }
   
   if(data_master==2)   {
      Wire.onRequest(cara_mereni);
      }
      }
      loop();
}




void ultrazvuk_mereni()   {
    
    pinMode(pingPin, OUTPUT);
    digitalWrite(pingPin, LOW);
    delayMicroseconds(2);
    digitalWrite(pingPin, HIGH);
    delayMicroseconds(5);
    digitalWrite(pingPin, LOW);
  
    pinMode(pingPin, INPUT);
    duration = pulseIn(pingPin, HIGH);
  
    pinMode(pingPin,OUTPUT);
    delay(10);
    cm = microsecondsToCentimeters(duration);
    
    Wire.write(cm);
    loop(); 
    }
     
     long microsecondsToCentimeters(long microseconds){
     return microseconds / 29 / 2;
     }
 
 
 
 
 
 
void cara_mereni()   {
    leveKraj=digitalRead(7);
    leveStred=digitalRead(8);
    praveStred=digitalRead(9);
    praveKraj=digitalRead(10);
  if(leveKraj&&leveStred&&praveStred&&praveKraj==HIGH)  {
     Wire.write(3);
     loop();
     }
     
  if(leveStred==HIGH)   {
     Wire.write(1);
     loop();
     }
     
  if(praveStred==HIGH)  {
     Wire.write(2);
     loop();
     }
  
  if(praveStred&&leveStred==LOW)   {
     Wire.write(0);
     loop();
     }   
     loop();
} 


Chtěl bych se zeptat jestli máte zkušenost s napájením arduina(uno) pomocí externího stabilizátoru např. 7805 přímo na pin Vin.Jsou nějaké rizika krom záměny polarity?Jde o to, že mám lcd, které má spotřebu cca 60mA(pokud dám na led podsvícení odpor 10ohmů) bez odporu to žere přes 200mA.Já ho chci připojit přímo k arduinu přes modul http://www.easyduino.cz/I2C-IIC-SPI-TWI ... je-d78.htm
společně se servem a ještě několika diodami.Celková spotřeba by se měla pohybovat do 500mA.Podle informací samotný stabilizátor na arduinu dá max 200mA což je málo.Jak to řešíte, když potřebujete věští proudy?
AlesH
Příspěvky: 323
Registrován: 25 úno 2013, 09:18

Re: Dva progrmy a I2C

Příspěvek od AlesH »

OK, takže pokud to dobře chápu, tak hlavní změnou, která rozchodila slave program podle Tvého očekávání, bylo přesunutí zpracování dat z masteru z "loop" do "vyber_programu"? Je to tak?

Taky jsem ještě našel nějaké změny v testování logických úrovní v podprogramu "cara_mereni". Předtím to bylo chybně?
haas

Re: Dva progrmy a I2C

Příspěvek od haas »

Ano, přesunul jsem to do loop, ale celé je to jako Slave.Ta změna logických úrovní byla předtím opačně.Nějak jsem si to popletl.Černá je HIGH ne LOW.
Jaký proud je schopný dodat stabilizátor na arduinu?
hubacekp
Příspěvky: 259
Registrován: 24 úno 2013, 13:40

Re: Dva progrmy a I2C

Příspěvek od hubacekp »

Máte na mysli proud z jednoho digi pinu? 40mA
Podle použitého procesoru se to pak drobně liší.
haas

Re: Dva progrmy a I2C

Příspěvek od haas »

Myslím celkový proud ze stabilizátoru na desce.zkoušel jsem připojit servo přímo na desku arduina, ale po zapnutí se celé zařízení odpojilo od pc( napájel jsem to přes USB)
petr-kubac
Příspěvky: 96
Registrován: 24 úno 2013, 15:43
Bydliště: Frydek - Mistek
Kontaktovat uživatele:

Re: Dva progrmy a I2C

Příspěvek od petr-kubac »

Vytahovat procesor z patice a strkat jej do desky Arduina a zpátky je zvěrstvo - ale jelikož Arduino je Open Hardware - stačí se podívat jak ATMEGA 328 z Arduina vlastně komunikuje s PC - tipoval bych že pomocí předovníku USB - RS232 typu FT232RL - a pomocí hohoto čipu byste mohl vyrobit adaptér, kdy PC by si myslelo že programuje Arduino a přitom by procesor seděl ve své patici v robotu.

Mimochodem moji roboti vznikli dávno před Arduinem, proto já programuju AVR přes ISP port a všechny procesory mám v robotech natvrdo připájené
"The best computer language is a solder" - "Nejlepší programovací jazyk je pájka" - Bob Pease
http://petr-kubac.blog.cz/
Odpovědět