Not enough Memory Fehler bei Lua Skript

CHDK-Skripte, CHDK-Entwicklung, PC-Zusatzprogramme, Informationen für Tüftler

Not enough Memory Fehler bei Lua Skript

Beitragvon dorumn » 22.01.2012, 18:09

Hallo,

ich habe ein Problem mit der A620 und CHDK. Ich steuere die Kamera ausschließlich remote mit dem Tool CHDKPTP (R57) unter Windows XP. Dies funktioniert soweit auch weitestgehend reibungslos.

Ich benötige für die Weiterverarbeitung in einem meiner Skripte eine Auflistung aller, auf der Kamera gespeicherten Bilder inklusive Unterordner, also eine Art "ls". Dies realisiere ich mit dem folgenden Lua Code:

Code: Alles auswählen
luar
imgRootDir = 'A/DCIM';
imageList = '\n';
for i,folder in ipairs(os.listdir(imgRootDir,false)) do
  for j,image in ipairs(os.listdir(imgRootDir..'/'..folder,false)) do
    imageList = imageList..imgRootDir..'/'..folder..'/'..image..'\n';
  end
end
return imageList


Der normale "ls" Befehl funktioniert bei mir hingegen nicht rekursiv und bringt die Kamera teilweise sogar zum Absturz, daher der Eigenbau. Soweit funktioniert das auch. Habe ich beispielsweise 50 Bilder auf der SD Karte, bekomme ich die Namen der Bilder inklusive Pfad angezeigt. Das Problem entsteht, wenn ich mehr als 250 Bilder auf der Kamera gespeichert habe. Dann bekomme ich die Fehlermeldung "Not enough memory".

Nun habe ich gelesen, dass der RAM der älteren Kameras wie der A620 ziemlich begrenzt ist und dass man das Problem mit einer selbst kompelierten CHDK Version lösen kann, in die man nur die Dinge übernimmt, die für den Betrieb unbedingt notwendig sind. Ich habe mir also das Komplettpaket der CHDK-Shell (V3.40) heruntergeladen und entpackt. Nach dem Start und dem Download des aktuellen Source Codes wählte ich in der Liste der Kameras meine A620 mit Firmware 1.0.0F aus. Anschließend habe ich unter Compile Options alles bis auf die folgenden Pakete abgewählt: Debugging, Qbasic, Lua (alle 4 Pakete) und PTP. Den Lua Interpreter benötige ich genauso wie das PTP Interface. Bei den anderen zwei war ich mir nicht ganz sicher. Nach dem Klick auf Compile Selected wurde nach ca. 45 Sekunden im Ordner /de/trunk/trunk925/bin die Datei a620-100f-1.1.0-r925-full.zip erfolgreich erstellt. Diese ist tatsächlich einige KB kleiner als die Standarddatei für meine Kamera. Nach dem Installieren auf die SD Karte via CardTricks startet die Kamera zwar wie gewohnt aber ich bekomme den gleichen "No Memory" Fehler wie zuvor. Die neue CHDK Version wurde definitiv geladen, das habe ich mit dem folgenden Befehl überprüft:
Code: Alles auswählen
chdkptp.exe -c -e"luar return get_buildinfo()"


Ist immernoch zu wenig RAM verfügbar? Das ist seltsam, da doch zumindest etwas weniger Arbeitsspeicher verbraucht werden sollte. Auch wenns nicht viel ist, so sollten doch z.B. jetzt 260 Bilder ausgegeben werden, bevor der "Not enough Memory" Fehler auftritt. Kann man an einer anderen Stelle evtl. noch mehr Komponenten abwählen oder muss ich auf der Kamera noch etwas einstellen? Oder liegts vielleicht an etwas ganz anderem? Bei der Canon A480 tritt dieses Problem nicht auf.

Ich bin für jede Hilfe dankbar
Viele Grüße
dorumn
CHDK-Einsteiger
CHDK-Einsteiger
 
Beiträge: 12
Registriert: 11.05.2011, 18:46
Kamera(s): Canon Powershot A620
Canon Powershot A480

Re: Not enough Memory Fehler bei Lua Skript

Beitragvon naddel » 22.01.2012, 21:10

Hallo dorumn,

- Rekursive Konstruktionen sind immer heikel, aber immerhin fängt lua das Problem ab und hängt nicht.
- Manche Fremddateien mit für das Kamerabetriebssystem nicht konformen Namen z.B. zu lang, mit Leerstellen
oder Sonderzeichen verursachen Probleme. z.B. Kopie von .....
--> auf solche Dateien prüfen und entfernen oder 8.3 Namen vergeben.
- Bei deiner Konstruktion wird alles in eine Stringvariable gespeichert. Deren mögliche Länge ist meist begrenzt.
Möglicherweise ist also nur der Platz in der Variablen erschöpft.
-----> Information auf mehrere Variablen aufteilen.
- leider habe ich einige Einzelheiten von LUA vergessen, aber soweit ich mich erinnere werden
Zeilen von links nach rechts interpretiert. Das könnte heißen (z.B. in Pascal wäre es so),
daß für die Zeile mit der du einen Eintrag hinzufügst und der 5 Stringadditionen .. beinhaltet
5x der Platz für die gesamte Liste zur Verfügung stehen müsste.
---> in diesem Fall hülfe es den neuen Eintrag auf einer Hilfsvariablen zusammenzusetzen
und diese in einer 2. Zeile an die Gesamtliste anzuhängen.

Falls das alles nichts hilft. Platz sparen!
- Redundante Informationen nur einmal speichern. z.B. Liste aller Verzeichnisse anlegen. danach zu jedem
Verzeichniseintrag eine Liste der Dateien im Verzeichnis. Damit sollten mindestens doppelt soviele Dateien
erfasst werden können.
- Wenn das noch nicht reicht. Die Liste als Datei führen.

Gruß Naddel
Zuletzt geändert von naddel am 24.01.2012, 05:13, insgesamt 1-mal geändert.
S2 1.00f mit aktueller DE Version
Benutzeravatar
naddel
CHDK-Begeisterter
CHDK-Begeisterter
 
Beiträge: 156
Registriert: 26.01.2009, 19:42
Kamera(s): G3 s2 ixusii

Re: Not enough Memory Fehler bei Lua Skript

Beitragvon rudi » 23.01.2012, 09:35

Hallo dorumn,
dorumn hat geschrieben:
Code: Alles auswählen
chdkptp.exe -c -e"luar return get_buildinfo()"
Schreibfehler?

Ich arbeite nicht mit chdkptp.exe sondern mit der ptpcam.exe, aber
Code: Alles auswählen
luar return
führt bei mir zur einer Fehlermeldung.
Verwende doch besser
Code: Alles auswählen
lua return ...
oder
Code: Alles auswählen
luar ...

Gruß rudi
Benutzeravatar
rudi
CHDK-Spezialist
CHDK-Spezialist
 
Beiträge: 510
Registriert: 11.09.2009, 11:27
Kamera(s): A590IS_101B, SX260_100B

Re: Not enough Memory Fehler bei Lua Skript

Beitragvon dorumn » 26.01.2012, 18:55

Hallo naddel,

Hab jetzt mal einiges ausprobiert:
An den Dateinamen kanns nich liegen, die Bilder werden alle korrekt in 8.3 Form abgespeichert, also z.B. ein kompletter Eintrag = A/DCIM/102CANON/IMG_1234.JPG
Das Aufsplitten der String Variablen habe ich in mehreren Varianten versucht, ebenso die Verwendung einer Hilfsvariable zum Zusammensetzen, bringt alles nichts.

Als nächstes versuchte ich Platz zu sparen:
Code: Alles auswählen
luar imgRootDir = 'A/DCIM';
counter = 0;
imageList = '\n';
for i,folder in ipairs(os.listdir(imgRootDir,false)) do
  imageList = imageList..imgRootDir..'/'..folder..'/IMG_\n';
  for j,image in ipairs(os.listdir(imgRootDir..'/'..folder,false)) do
    imageList = imageList..string.sub(image,5)..'\n';
    counter = counter+1;
  end
end
imageList = imageList..'anzahl bilder = '..counter;
return imageList


Eine Beispielausgabe wäre dann:
A/DCIM/102CANON/IMG_
1234.JPG
2345.JPG
...
7890.JPG

Das hat schonmal dazu geführt, dass ich mehr Bilder speichern kann. Theoretisch sollten es statt der 250 über 600 sein,, da ich den gesamten Pfad und damit 20/28 pro Zeile einspare. Leider war dem in der Praxis nicht so, ich habs mit 500 Bildern probiert und der gleiche No memory Fehler tritt wieder auf. Die Kamera kann maximal eine 2GB SD Karte aufnehmen. Das entspricht etwa 650 Bildern und so viele müssen dann im Extremfall in den Speicher passen.

Als letztes hab ich noch versucht, die abgearbeiteten Ordner direkt auf stdout zu schreiben, etwa so:
Code: Alles auswählen
luar imgRootDir = 'A/DCIM';
counter = 0;
imageList = '\n';
for i,folder in ipairs(os.listdir(imgRootDir,false)) do
  for j,image in ipairs(os.listdir(imgRootDir..'/'..folder,false)) do
    imageList = imageList..imgRootDir..'/'..folder..'/'..image..'\n';
    counter = counter+1;
  end
  write_usb_msg(imageList);
  imageList = '\n';
end
return counter


Das funktioniert auch mit 600 Bildern, hat dafür aber den Nachteil, dass es sehr langsam läuft. Während die Variante drüber das Ergebnis nach etwa 2 bis 3 Sekunden zurückgibt, braucht diese Lösung zwischen 5 und 7 Sekunden und das ist leider zu viel.

Gibts noch eine andere Möglichkeit, die ich ausprobieren kann?

Hallo rudi,
rudi hat geschrieben:
dorumn hat geschrieben:
Code: Alles auswählen
chdkptp.exe -c -e"luar return get_buildinfo()"
Schreibfehler?


Nein, darüber habe ich mich auch schon gewundert. Wenn ich
Code: Alles auswählen
chdkptp.exe -c -e"lua return get_buildinfo()"

oder
Code: Alles auswählen
chdkptp.exe -c -e"luar get_buildinfo()"

verwende, bekomme ich überhaupt nichts zurück. Es funktioniert tatsächlich nur
Code: Alles auswählen
chdkptp.exe -c -e"luar return get_buildinfo()"

Daher findet man diese Kombination auch bei meinen obigen Lua Skripten.

Viele Grüße
dorumn
dorumn
CHDK-Einsteiger
CHDK-Einsteiger
 
Beiträge: 12
Registriert: 11.05.2011, 18:46
Kamera(s): Canon Powershot A620
Canon Powershot A480

Re: Not enough Memory Fehler bei Lua Skript

Beitragvon rudi » 26.01.2012, 20:07

Hallo dorumn,
dorumn hat geschrieben:Gibts noch eine andere Möglichkeit, die ich ausprobieren kann?

Die PTPCamGUI arbeitet mit einer Hilfsdatei um die Dateiinformationen zu übermittel. Dafür wird kein Speicherplatz im RAM benötigt. Ich habe diese Variante mit über 2500 Bilder getestet. Es wird zusätzlich noch die Erstellungszeit gespeichert.

Dieser Code wird dabei verwendet:
Syntax: [ Download ] [ Verstecken ]
Benutze Lua Syntax Highlighting
-- begin -- DCIM Download --
local function getfileson(path,hfile)
  local fd,c,s,fpath,stat,i,tc,ts=os.listdir(path),0,0
  if fd~=nil and #fd>0 then
    for i=1, #fd do
      fpath=path .. "/" .. fd[i]
      stat=os.stat(fpath)
      if stat~=nil then
        if stat.is_dir==true then
          if fd[i]~="CANONMSC" then
            tc,ts=getfileson(fpath,hfile)
            c=c+tc
            s=s+ts
          end
        elseif stat.is_file==true then
          hfile:write(path .. "/"  .. "|" .. fd[i] .. "|" .. os.date("%Y%m%d%H%M%S", stat.mtime) .. "\n")
          s=s+(stat.size-1)/4096+1
          c=c+1
        end
      end
    end
  end
  return c,s
end

local function getdcimfiles()
  local fn,count,size,tc,ts="A/ptpgui.txt",0,0
  local file=io.open(fn,"wb")
  if file then
    tc,ts=getfileson("A/DCIM",file)
    count=count+tc
    size=size+ts
    file:close()
  end
  if count>0 then size=(size-1)/256+1 else size=0 end
  return count .. "\n" .. fn .. "\n" .. size
end
-- end -- DCIM Download --
Erstellt in 0.011 Sekunden, mit GeSHi 1.0.8.9


Der Aufruf erfolgt mit
Syntax: [ Download ] [ Verstecken ]
Benutze Lua Syntax Highlighting
return getdcimfiles()
Erstellt in 0.004 Sekunden, mit GeSHi 1.0.8.9
Zurück erhält man einen String mit den Angaben über die Anzahl der Bilder, den Dateinamen und den benötigten Speicherplatz.

Gruß rudi
Benutzeravatar
rudi
CHDK-Spezialist
CHDK-Spezialist
 
Beiträge: 510
Registriert: 11.09.2009, 11:27
Kamera(s): A590IS_101B, SX260_100B

Re: Not enough Memory Fehler bei Lua Skript

Beitragvon naddel » 27.01.2012, 02:29

Hallo dornum,

Die Verzeichnisfunktionen von Rudi sind alterprobt, bei den Lua Beispielen findest du auch etliche Verzeichnisauflistungen.

Nachdem die anderen Fehlerquellen ausgeschlossen sind besteht das Problem aus den zu langen Zeichenketten. Und dabei wahrscheinlich am erhöhten Speicherbedarf beim verketten von Strings.
Eine komplexe Variable wie ein Array kann den kompletten Speicher belegen.

warum willst du das unbedingt als einen String haben.

Aufteilen geht bei deinem Eingangsbeispiel z.B. so
Syntax: [ Download ] [ Verstecken ]
  1. imgRootDir = 'A/DCIM'; 
  2. liste={}; 
  3. for i,folder in ipairs(os.listdir(imgRootDir,false)) do 
  4.  for j,image in ipairs(os.listdir(imgRootDir..'/'..folder,false)) do 
  5.   liste[#liste+1]=imgRootDir..'/'..folder..'/'..image..'\n';  
  6.  end 
  7. end 
  8.  
  9. for i=1,#liste do 
  10.   print(liste[i]); 
  11. end 


jetzt ist jeder Eintrag ein String.
luar gibt das ganze aber mit return liste als einen String zurück.
dein Beispiel geht aber davon aus, daß
- alle Einträge auf DCIM Verzeichnisse sind
- alle Einträge auf den Unterverzeichnissen Bilder sind

Platzsparen geht z.B. so
(Verzeichnispfad nur einmal speichern)

Syntax: [ Download ] [ Verstecken ]
  1. imgRootDir = 'A/DCIM'; 
  2. liste={}; 
  3.  
  4. for i,folder in ipairs(os.listdir(imgRootDir,false)) do 
  5.  liste[i]=imgRootDir..'/'..folder 
  6.  liste[i]={} 
  7.  for j,image in ipairs(os.listdir(imgRootDir..'/'..folder,false)) do 
  8.   liste[i,j]=image..'\n';  
  9.  end 
  10. end 
  11.  
  12. for i=1,#liste do 
  13.  for j=1,#liste[i] do 
  14.   print(liste[i]..liste[i][j]); 
  15.  end 
  16. end 


Es bestehen die gleichen Einschränkungen wie oben
keinerlei Fehlersicherheit.
Darum halt dich lieber an die Beispiele von Rudi und msl

genereller Speichermangel wirds nicht sein 1000 Dateien zu 25 Byte = 25kB sollten locker drin sein.

Die Beispiele deshalb nur um zu zeigen wie man lange Strings umgeht.
Arrays anlegt und aufruft.

Gruß naddel
S2 1.00f mit aktueller DE Version
Benutzeravatar
naddel
CHDK-Begeisterter
CHDK-Begeisterter
 
Beiträge: 156
Registriert: 26.01.2009, 19:42
Kamera(s): G3 s2 ixusii


Zurück zu Code-Ecke

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 23 Gäste

cron