Elektroda.pl
Elektroda.pl
X

Wyszukiwarki naszych partnerów

Wyszukaj w ofercie 200 tys. produktów TME
Europejski lider sprzedaży techniki i elektroniki.
Proszę, dodaj wyjątek elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Step7 s7-300 problem ze wskaznikami i adresowaniem posrednim

Goompas 15 Cze 2007 14:18 14389 35
  • #1 15 Cze 2007 14:18
    Goompas
    Poziom 13  

    Witam
    Chcialbym zrobic aby do db15 poczawszy od bajtu 0 co 2 do 8 byly zapisywane odczyty pomiaru czujnikiem analogowym.
    Najpierw przy inicjacji robie LAR1 P#0.0
    Ponizej jest wycinek czesci programu wykonywany cyklicznie 5 razy, zeby zapisac 5 pomiarow do db

    Code:

          A     #odczytano
          OPN   "AnalogDane"
          L     "OdczytAnalog"
          T     DBW [AR1,P#0.0]
          +AR1  P#2.0 //tutaj powinno byc przesuniecie adresu o 2 bajty?
          S     #zapisanodoDB
          R     #odczytano

    Problem jest taki ze wszystkie 5 pomiarow jest zapisywanych do db15.dbw0 nadpisujac poprzedni(wskaznik nie jest przesuwany o 2?) zamiast db15.dbw0, db15.dbw2, db15.dbw4, db15.dbw6, db15.dbw8

    Chcialem to zrobic tez w taki sposob
    Prtzed petla:
    L P#0.0
    T "AdresDBDlaAnalog"
    a w petli
    Code:


          A     #odczytano
          OPN   "AnalogDane"
          L     "OdczytAnalog"
          T     DBW ["AdresDBDlaAnalog"]
          L     "AdresDBDlaAnalog"
          L     2
          +D
          T     "AdresDBDlaAnalog"       //gdy jest ta linijka, cpu przechodzi w stan stop
          S     #zapisanodoDB
          R     #odczytano

    Jednak cpu wywala sie przy zaznaczonej linijce, gdy jej brak to cpu sie nie wywala.
    "AdresDBDlaAnalog" to zmienna typu MD 110

    Bede wdzieczny za wszelkie uwagi

    0 29
  • #2 15 Cze 2007 15:20
    mik2002
    Poziom 10  

    Co do pierwszego kodu - sprzwdź czy przypadkiem nie inicjalizujesz za każdym razem wskaźnika P#0.0. Jeżeli za każdym razem wykonyqwana jest instrukcja LAR1 P#0.0, sterownik powróci do adresu inicjalizacji

    w drugim kodzie sterownik przechodzi w stan stop prawdopodobnie dlatego że w komórce pamięci zawarty jest adres który nie istnieje w podanym DB - wyskakuje poza blok danych.

    osobiście proponowałbym zrobić to na zasadzie rejestru przesuwnego - przesuwać dane tak, aby najstarsze były pod najwyższym adresem w DB, należy to robić od końca

    Powodzenia

    0
  • #3 15 Cze 2007 15:53
    Goompas
    Poziom 13  

    LAR1 P#0.0 jest inicjowane poza glowna petla, swiadczy o tym nawet to ze w tym samym networku co LAR1 P#0.0 mam zerowanie licznika petli, ktory zlicza tak jak ma zliczac, gdyby LAR1 P#0.0 bylo wykonywane, to mialbym takze reset licznika petli a tak nie jest.
    Cos tu nie tak jest w tym kodzie, chyba?
    Moze chodzi o to ze OPN "AnalogDane" jest za LAR1 P#0.0 a powinno byc przed?
    Chociaz probowalem i zrobic tak i nie dzialalo.

    Co do Twojej propozycji to nie bardzo rozumiem o co chodzi, mozesz jakos bardziej to naswietlic, chociaz wolalbym zrobic to wykorzystujac wskazniki.

    0
  • #4 15 Cze 2007 16:11
    mik2002
    Poziom 10  

    chyba sie troche zapedzilem:) W drugim kodzie jest blad adresacji. jezeli w MD110 masz wskaznik
    P#0.0
    nastepnie wykonasz instrukcje
    L 2
    otrzymasz wskaznik
    P#0.2
    jezeli chcesz przesunac wskaznik o wartosc #2.0 nalezy dodac instrukcje
    SLD 3
    przed transferem

    Dodano po 14 [minuty]:

    Co do mojej propozycji z rejestrem przesuwnym
    robie to w tem sposob, ze zawsze do adresu pierwszego przypisuje wartosc rzeczywista, natomiast w petli umieszczam przesuniecie wartosci poprzednich (od najstarszej):
    L DBD[AR1,P#0.0]
    T DBD[AR1,P#2.0]
    potem zmniejszasz wartosc indeksu o 2.0 az do uzyskania indeksu zerowego w ktorym zawarta jest wartosc rzeczywista, wtedy opuszczasz petle

    0
  • #5 18 Cze 2007 07:29
    Goompas
    Poziom 13  

    Ale z SLD 3 nie bedzie dzialalo tak jak chce, gdyz za pierwszym razem owszem bedzie wskazywalo na drugi element, ale juz za drugim przejsciem petli bedzie wskazywalo na 16 element.
    Tu chodzi o samo dodanie do wskaznika wartosci przesuniecia o 2 slowa(word), tak aby za kazdym przejsciem petli wskaznik przesuwal sie stale o 2 slowa.

    0
  • #6 21 Cze 2007 15:54
    ThoronDC
    Poziom 14  

    Witam

    Zamiast
    L 2
    +D

    Powinno być

    L P#2.0
    +D
    dodajemy wskaźnik

    lub

    L 2
    SLD 3
    L "AdressDBDlaAnalog"
    +D

    Pozdrawiam

    0
  • #7 29 Paź 2007 20:57
    wachman
    Poziom 13  

    witam,
    nie rozumiem do końca tych wskaźników ale....
    chcę zwiększyć wskaźnik "Area" o 2 bajty,
    robię tak:

    L P##Area //Area - wskaznik typu ANY
    L P#2.0
    +D

    i gdzie to załadować ?? chciałbym ponownie do wskaźnika "Area"....

    0
  • #8 30 Paź 2007 05:55
    andy1955
    Specjalista Automatyk

    tu roi aż się od błędów i od błędnego rozumowania.
    1. rozkaz "L" zostaje zawsze wykonywany,niezależnie od VKE (wyniku logicznego powyżej) tzn. w każdym cyklu (co kilka-dziesiąt ms) będzie odczytywana wartość na wejściu.
    2. pomieszane są tu dwie metody adresowania pośredniego (SLD3 z poinerem)
    3. co ma być warunkiem odczytu (impuls czasu )?
    4.jak wygląda pętla zliczająca pomiary ?
    5. co ma oznaczać:
    A #odczytano
    ........
    S #zapisanodoDB
    R #odczytano

    0
  • #9 30 Paź 2007 13:31
    wachman
    Poziom 13  

    nie wiem co chciał uzyskać autor tematu ale patrząc na datę pierwszego postu to już to zrobił albo zaniechał,
    dołączyłem się do rozmowy ponieważ ostatni post traktował o inkrementacji wskaźnika i z tym mam problem,

    używam funkcji która zwraca mi wskaźnik typu ANY, chcę teraz żeby wskazywał o np. 3 bajty do przodu, zamierzam go inkrementować cyklicznie,

    b. proszę o pomoc

    0
  • #10 30 Paź 2007 17:54
    andy1955
    Specjalista Automatyk

    przede wszystkim pytanie: sam napisałeś tą funkcję lub jest to funkcja standardowa -siemensa. ANY-Poiner to 10 bytów.
    To powinno chodzić:

    LAR1 P##Quelle //Lade die Anfangsadresse des ANY–Pointers in AR1.

    L LD [AR1,P#6.0]
    L P#3.0
    +AR1
    T LD [AR1,P#6.0]



    Ten podprogram musisz umieścić po funkcji ,której wynikiem jest ANY (Quelle). ANY będzie wtedy przepisywany w pamięci z uwzględnieniem nowego adresu podwyższonego o trzy bajty.

    0
  • #11 31 Paź 2007 07:36
    wachman
    Poziom 13  

    używam funkcji z przykładu Siemens'a,
    ta funkcja to:

    Code:
          L     P##Area_pointer             //Load start address
    
          LAR1                              //Loadin address register AR1
          L     W#16#10                     //Load syntax-ID and transfere
          T     B [AR1,P#0.0]               //to the actual start address 0
          L     #Type_of_data               //Load type of data and transfere
          T     B [AR1,P#1.0]               //to actual start address 1
          L     #Number_of_data             //Load Number_of_data and transfere
          T     W [AR1,P#2.0]               //to actual start address 2
          L     #DB_No                      //Load DB_No and transfere
          T     W [AR1,P#4.0]               //to actual start address 4
          L     P##Area_start               //Load area start address
          LAR2                              //Load in address register AR2
          L     #Offset                     //Load the offset
          SLD   3
          +D                                //Addition of area start address and offset
          L     DW#16#FFFFFFF8              //Masking the rest of data
          AD   
          LAR2                              //Load in address register AR
          T     D [AR1,P#6.0]               //Output of new calculated start address
          BEU   

    @andy1955, to co podałeś niestety nie działa :cry:

    0
  • #12 31 Paź 2007 09:23
    andy1955
    Specjalista Automatyk

    poniżej mój program, za pomocą którego kopiuję ilość zdefiniowanych bajtów ze zdefiniowanego DB oraz ze zdefiniowanego adresu początkowego do zdefiniowanego celu.Program pracuje w 100%. Rozpakować Stepem7.
    Programem tym da się praktycznie wszystko z DB skopiować (String,Word,Time) ,najważniesze - podanie odpowiedniej ilości bajtów do skopiowania.
    (Mnemonika niemiecka):
    Wejścia funkcji wymagają zmiennych w postaci "Integer", a więc łatwo można dodać wartość offsetu.

    1
  • #13 05 Lis 2007 17:17
    Oskarr
    Poziom 12  

    Proponuje użyć funkcji BLOCK MOV :)
    Możesz sobie kopiować do woli wszystko wszędzie jeżeli jest ciągły obszar :)
    Natomiast jeżeli chcesz kopiować fragmenty DB np. co drugi rejestr to zrób to w pętli. Inicjujesz na P#0.0 przed pętlą apotem w pętli inkrementujesz go o P#2.0. Proste :)

    0
  • #14 05 Lis 2007 19:33
    andy1955
    Specjalista Automatyk

    Oskarr, ja także wykorzystałem w moim programie funkcję BLOKMOV z biblioteki Step7. Samą funkcją BLOKMOV możesz skopiować dane adresując bezpośrednio źródło i cel.
    Chcąc kopiować dane z jednego DB (numer DB zależny np. od numeru narzędzia) do drugiego DB, którego numer zależny jest od np. typu materiału
    musisz stworzyć ANY POINTER adresując pośrednio. I to właśnie robi mój program (zamiast stałych wartości podstawić tylko zmienne typu Integer) .

    0
  • #15 06 Lis 2007 07:27
    Oskarr
    Poziom 12  

    Gadzam sie że do BLOCK MOV nalezy użyć formatu ANY nie da sie inaczej.
    Tylko nie bardzo wiem co u Ciebie oznaczo to urządzenie :/

    0
  • #16 06 Lis 2007 17:56
    andy1955
    Specjalista Automatyk

    Cytat:
    Tylko nie bardzo wiem co u Ciebie oznaczo to urządzenie :/

    Nie bardzo wiem o co chodzi ale nie szkodzi.
    Napisz krótki program, który będzie kopiował 70 bajtów z DB [xx] do DB[yy] przy czym xx = wartość, która zmienia się od 0 do 50 ; wartość yy = wartość od 51 do 100 . Adres początkowy i docelowy DBW zz może się zmieniać w czasie procesu np. od 0 do 256. Również zmienne xx i yy mogą przybierać różne wartości podczas procesu.
    Jeśli tą funkcję zaprogramujesz to będziesz wiedział o co mi chodzi .:D

    0
  • #17 05 Sty 2008 15:45
    mariusz.sek
    Poziom 10  

    Witam,
    Chciałbym wrócić jeszcze raz do tematu zapisywania wyników do bloków danych z wykorzystaniem wskaźnika.
    W moim programie chciałbym zapisywać aktualną prędkość obrotową silnika do DB tylko jakoś nie udaje mi się tego zrobić.
    Przy wywołaniu funkcji zapisującej do DB

    Code:

     OPN   DB    10
          L     MW    12
          T     DBD [DBD 2]
          L     DBD    2
          L     P#2.0
          +D   
          T     DBD    2

    zostaje wykonany zapis do bloku danych tylko, tylko że jest to ostani wynik pomiaru.
    Zostaje zapisany zgodnie z wartością wskaźnika, czyli co wywołanie funkcji zapisującej co drugi bajt do bloku danych. W efekcie w DB mam same zera tylko na ostatnie pozycji jest ostatnia zapisana wartość prędkości.
    Funkcja zapisująca jest wywoływana cyklicznie co 200ms i przy jedynce logicznej na odpowiednim wyjściu cyfrowym. W DBD2 mam zapisaną początkową wartość wskaźnika (P#10.0), czyli miejsce gdzie powinien zostać zapisany pierwszy wynik.
    Może ktoś już miał podobny problem i mógłyby podzielić się swoją wiedzą.
    Może błąd tkwi w sposobie wywoływania funkcji zapisu ?
    Czy na kasowanie poprzednich danych w tym bloku może miec wpływ to, że w w funkcji wywołującej zapis do tego bloku danych jest wywoływana drugi blok danych ?

    0
  • #18 06 Sty 2008 03:12
    MidVis
    Poziom 10  

    Witam,
    popełniasz błąd zapisując WORD do DOUBLE, a następnie przesuwając o 2 Bajty = 1 WORD. Zmodyfikuj kod następująco:

    OPN DB 10
    L MW 12
    T DBW [DBD 2] // bylo: T DBD[DBD 2]
    L DBD 2
    L P#2.0
    +D
    T DBD 2

    Powinno być ok.

    0
  • #19 06 Sty 2008 07:55
    andy1955
    Specjalista Automatyk

    Cytat:
    Powinno być ok.

    sprawdzałeś ? Pomyśl jeszcze raz.

    0
  • #20 07 Sty 2008 00:41
    MidVis
    Poziom 10  

    Cytat:
    sprawdzałeś ? Pomyśl jeszcze raz


    Sprawdziłem przed chwilą i działa. Nie wiem jak funkcjonuje reszta programu, ale adresowanie pośrednie jest rozwiązane poprawnie.
    Nawiasem mówiąc, wydaje mi się, że kolega mariusz.sek nie zauważyłby błedu w kodzie, gdyby kolejność bajtów nie była w Simaticu zamieniana. Tak wynika z opisanego zachowania sterownika.

    0
  • #21 07 Sty 2008 18:51
    andy1955
    Specjalista Automatyk

    sprawdziłem symulatorem i wyskakuje mi błąd SF. Dziwne,że u ciebie wszystko hula.
    Adres jest zapamiętywany w DB10.DBD2 tzn. DBD2 = DBW2+DBW4.
    Po przetransferowaniu pointera #2.0 do DBD2
    wartość z MW12
    L MW 12
    T DBW [DBD 2] = T DB10.DBW2 zostaje wpisana do obszaru adresowego !! i tutaj wyskakuje błąd.

    0
  • #22 07 Sty 2008 19:46
    MidVis
    Poziom 10  

    >Po przetransferowaniu pointera #2.0 do DBD2

    Początkowa wartość DBD2 była P#10.0 , dalej transferujemy inkrementację (o P#2.0) wartości początkowej. Zakładam, że odpowiednio zainicjowałeś wcześniej DBD2, więc zastanawiam się czy może to być problem z symuatorem. Ja symulatora nie używam i nie posiadam. Sprawdzałem na sterowniku.

    0
  • #23 07 Sty 2008 22:05
    mariusz.sek
    Poziom 10  

    Cytat:
    Początkowa wartość DBD2 była P#10.0

    I cały czas jest. Jutro sprawdzę na sterowniku i zobaczymy czy chodzi po prostu o błędne przypisanie DWord'a do Worda.

    0
  • #24 08 Sty 2008 13:33
    rogasss
    Poziom 9  

    Witam,
    dyskutujecie na temat jaki by mnie troche interesował. Otóż potrzebuje uzupełnić DB zmiennymi przykładowo wartością timera w kolejnych chwilach.
    FB wygląda następująco:

    L 100
    T MB 1
    L P#20.0
    petl: T MD 100
    OPN DB 2
    L T 1
    T DBB [MD 100]
    L MD 100
    L P#3.0
    -I
    JP petl

    funkcja niby działa, z jednym błędem uzupełnia cały określony w FB zakres DB tymi samymi danymi.
    Step7 s7-300 problem ze wskaznikami i adresowaniem posrednim

    Tu jest ten problem jak wymusić jakieś przerwanie, nie ważne od czego: timer, jakiś bit, żeby zapis do DB w różnych wierszach miał różne wartości.
    Poza tym ta pętla której użyłem jakoś nie działa ale tylko ona nie powoduje mi zatrzymania symulatora.

    0
  • #25 09 Sty 2008 05:19
    andy1955
    Specjalista Automatyk

    dlaczego P#3.0 ?

    Cytat:
    L MD 100
    L P#3.0
    -I

    spróbuj:
    L MD 100
    L P#3.0
    -D
    zmodyfikowałem twój program dla sprawdzenia i działa:
    Cytat:
    L 100
    T MB 1
    L P#20.0
    petl: T MD 100
    AUF DB 2
    L MB 1
    T DBB [MD 100]

    L MB 1
    L 1
    -I
    T MB 1
    L MD 100
    L P#1.0
    -D
    SPP petl

    użyłem zamiast T1 MB1 i za każdym razem odjąłem od MB1 wartość 1 .
    Problemem jest czas przebiegu całej pętli.
    Będziesz musiał zdefiniować warunek przy którym zostanie odczytania T1

    0
  • #26 09 Sty 2008 15:38
    Oskarr
    Poziom 12  

    wystarczy cyklicznie wywoływać tą funkcje nap w OB35 i problem z głowy. Nie trzeba wtedy patrzeć na czas pętli.

    0
  • #27 09 Sty 2008 17:34
    andy1955
    Specjalista Automatyk

    Cytat:
    wystarczy cyklicznie wywoływać tą funkcje nap w OB35 i problem z głowy. Nie trzeba wtedy patrzeć na czas pętli.

    moim zdaniem to nie pomoże ponieważ czas trwania pętli - czas zapisu 20 wartości będzie może trwać 1ms i jest to obojętne gdzie się tą funkcję wywoła(pętla musi przebiec do końca). Co innego przerywać pętlę impulsem z OB35 ale można od razu zamiast pętli zastosowań skoki warunkowe i będzie po problemie.

    0
  • #28 09 Sty 2008 18:35
    Oskarr
    Poziom 12  

    Z tego co ja zrozumiałem należy wpisywać do rejestrów DB wartość jednego rejestru. Jeżeli zapisywać będzie się ten rejestr co czas T1 a pętla programowa będzie trwać T2 (pamiętając że zapisywany rejestr jest odświeżany na końcu pętli programowej a więc co czas T2). W takiej sytuacji zapis zmiennej do rejestrów DB powinien odbywać się z częstotliwością T1=T2, lub T1>=T2

    0
  • #29 10 Sty 2008 05:18
    andy1955
    Specjalista Automatyk

    przebieg całej pętli (20x) zostanie załatwiony w jednym cyklu, czyli 20 wartości zostanie w przeciągu np. 500µs zapisane do DB. A jaka jest rozdzielczość timera ? Czy można ustawić czas w microsekundach ??

    0
  • #30 10 Sty 2008 09:52
    Oskarr
    Poziom 12  

    Jeżeli chcemy zapisywać cyklicznie wartość pewnego rejestru (zapisywać jego wartość co określony czas) celem tego ma być zarejestrowanie zmian tego rejestru.
    To co koledzy opisują nie ma jakiegokolwiek sensu!!! Jeżeli w jednym cyklu programowym zapisuje się 20 próbek to każda próbka będzie miała tą samą wartość, dlatego że zapisywany rejestr jest uaktualniany co cykl programowy, a więc zapis 20 próbek (podejrzewam że z użyciem metody LOOP) spowoduje zapełnienie DB tymi samymi wartościami.
    Jeżeli chce się monitorować zmiany jakiegoś rejestru należy zapisywać go minimum co cykl programowy, a więc bez komendy LOOP. Mam nadzieje że dobrze was zrozumiałem.
    Chętnie pomogę w rozwiązaniu problemu jeżeli przedstawicie go w całości :))

    Dodano po 3 [minuty]:

    Zapisywanie wartości w pętli LOOP ma sens jeżeli odwołujemy się przez peryferia PLC. Wtedy w pętli programowej korzystamy z komendy LOOP ma to sens tylko wtedy jeżeli zapisujemy wartość np. PIW

    0
TME logo Szukaj w ofercie
Zamknij 
Wyszukaj w ofercie 200 tys. produktów TME
TME Logo