Forum Rule: Always post complete source code & details to reproduce any issue!
Page 2 of 2 FirstFirst 1 2
Results 26 to 45 of 45

Thread: Zmodem transfer from Teensy to PC

  1. #26
    Member
    Join Date
    Jan 2016
    Location
    USA
    Posts
    46
    I'm sorry if i wasn't clear. I want to send data from an SD which runs on a teensy 3.2 to an SD on a Nano. I assumed that your code would be fine on the teensy, but might not fit on a Nano in complete form. All i need to do on the nano is receive the data over a serial connection to the teensy.

    there is another likely problem which is that the nano serial connection is with SoftwareSerial. I wouldn't be surprised that this simply cannot be done without difficult-to-invent code.

    What do you thinK?

    john

  2. #27
    Junior Member
    Join Date
    Feb 2016
    Posts
    18
    Okay, I was hoping you wanted to send from the Nano, not receive to it. I don't know if that direction can be done. I'll let you know what I find.

    One last question then - when it's time to get files to the Nano, can the ZModem sketch be the only thing flashed/loaded/running on the Nano? IF I make this work, it will consume nearly every byte the Nano has both in Flash and RAM, there won't be room for anything else.

  3. #28
    Member
    Join Date
    Jan 2016
    Location
    USA
    Posts
    46
    You know, this may not be worth your effort. if I just belly up to the bar and replace the nano with a teensy, I'll be able to ditch softwareserial and use a hardware port, plus have plenty of room and you won't have to struggle to make it fit.

    I will need a few other things on the nano end and it just might make more sense to go to the teensy. I would need some headroom in any case for other things I may want to do.

    i would think that if you can make this work on an Uno, it would work on a Nano.

    let me know.

    John

  4. #29
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    Quote Originally Posted by jferguson View Post
    there is another likely problem which is that the nano serial connection is with SoftwareSerial. I wouldn't be surprised that this simply cannot be done without difficult-to-invent code.

    What do you thinK?

    john
    Opinion: Software serial (bit-banging with timer interrupts, not CPU loops) is OK for low speed (say, 9600 and down), half duplex (don't send and receive at the same time), and low duty cycles. Like incoming GPS sentences, keyboards, and so on.

  5. #30
    Junior Member
    Join Date
    Feb 2016
    Posts
    18
    John,

    I think you'll likely need to replace that Nano with a Teensy in any case because in my understanding SoftwareSerial provides absolutely no serial buffer and if that is the case the chances that this (or anything else that can provide some reliable data transfer) can work successfully with SoftwareSerial are pretty low.

    I'd like to have a version that can work on the Uno so the effort is a personal challenge regardless. It's just so darn close, I'm within a few bytes of success!

  6. #31
    Member
    Join Date
    Jan 2016
    Location
    USA
    Posts
    46
    Hi BF. it just occurred to me that since the nano isn't connected via the usb port while it's in use, I can use the hardware serial port. let me try this before we pursue this any farther.

    in any case, i'd be delighted to try what you do.

    john

  7. #32
    Junior Member
    Join Date
    Feb 2016
    Posts
    18
    With the hardware serial port you're still likely to run into some trouble at high speeds because the Arduino's small Hardware Serial so small at only 64 bytes. I can only get my Mega to receive ZModem transfers at 57600.

    I think the ZModem sketch can be made to work, just barely, on a smaller device with 32K of flash and 2K of RAM but it has to be configured for only ONE of send or receive. I'm still working on slimming up the send side enough to work reliably; it appears that receive actually works as I have it now (not yet uploaded to GitHub), in an Arduino Uno simulator anyway. I don't want to release it until I have it so it can be configured for either direction. I'll let you know if I make a breakthrough incase you want to try it out.

  8. #33
    Member
    Join Date
    Jan 2016
    Location
    USA
    Posts
    46
    sounds good to me.

  9. #34
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    Quote Originally Posted by bitflipper View Post
    With the hardware serial port you're still likely to run into some trouble at high speeds because the Arduino's small Hardware Serial so small at only 64 bytes. I can only get my Mega to receive ZModem transfers at 57600.
    I recall reading here that there's an easy way to increase the size of the Teensy UART buffers.

    I must say that using ZModem would be an overkill and bring lots of big code / RAM demands for a problem that is simpler.

  10. #35
    Junior Member
    Join Date
    Feb 2016
    Posts
    18
    Hi stevech,

    I wrote the ZModem sketch more so for use on simpler Arduino boards than the Teensy. Overkill, perhaps, but then it does handle auto-starting the download with the other side, handing off the file name, ensuring that the data is correct via CRC, and allowing for resuming downloads. For me, that's all pretty useful. Yes, it's quite hungry on memory, but I really meant for the sketch to be flashed on to the board for temporary use as a "Serial File Manager".

  11. #36
    Junior Member
    Join Date
    Feb 2016
    Posts
    18
    I'm waking this thread up again because you guys show more signs of life than the folks at forum.arduino.cc and I'm hoping someone will test my new sketch version on a small Arduino board.

    So jferguson and others who might be interested, I did a large scale overhaul to my ZModem sketch and I actually got it down (with a lot of very creative and unorthodox wrangling) to just under 30K of Flash and just under 2K of RAM needed. I even managed to do that and not have to choose to enable only one of send or receive. I didn't think it could be done at first, but it appears I proved myself wrong. I put some macros into zmodem_config.h that allow you to disable send, receive, or the file manager commands just incase, but I'm hopeful it's not necessary to do so.

    It would be fabulous if someone with an SDCard on an Uno, or better yet a Nano because it has little less flash available, would take the latest version for a test drive and let me know how it runs! Over here at GitHub:

    https://github.com/ecm-bitflipper/Arduino_ZModem

  12. #37
    Member
    Join Date
    Jan 2016
    Location
    USA
    Posts
    46
    Hi BF,
    let me take a look, but it'll take a day or two. it would probably be useful if you whipped up a sketch, too.

    nice going.

    john

  13. #38
    Junior Member
    Join Date
    Feb 2016
    Posts
    18
    John, it is a sketch as it stands. Have a look at my video
    for how to use it.

    Perhaps a good next step for it would be to break the ZModem functionality into a library and then make the file manager an "example sketch". As it stands right now, it's a stand alone sketch. Keep in mind that if you try to use it as a library on a board with only 2K of memory (Uno, Nano) that there is almost no memory left even if you comment out one of the macros in zmodem_config.h to disable one of either send or receive. Anything else the sketch is made to do will need to use very few bytes of memory.
    Last edited by bitflipper; 03-07-2016 at 12:38 AM. Reason: formatting

  14. #39
    Member
    Join Date
    Jan 2016
    Location
    USA
    Posts
    46
    I see now, sorry for my confusion. I should be able to get into this in the next day or so.

    thanks for your fine work,

    john

  15. #40
    Member
    Join Date
    Jan 2016
    Location
    USA
    Posts
    46
    what ar you compiling with? with the arduino 1.6.5 IDE I get these sorts of errors


    zmodem_rz.cpp.o:/usr/share/arduino/hardware/arduino/avr/cores/arduino/HardwareSerial.h:128: first defined here
    zmodem/zmodem_rz.cpp.o: In function `getfree()':
    /usr/share/arduino/hardware/arduino/avr/cores/arduino/HardwareSerial.h:128: multiple definition of `tryz()'
    zmodem_rz.cpp.o:/usr/share/arduino/hardware/arduino/avr/cores/arduino/HardwareSerial.h:128: first defined here
    zmodem/zmodem_rz.cpp.o: In function `getfree()':
    /usr/share/arduino/hardware/arduino/avr/cores/arduino/HardwareSerial.h:128: multiple definition of `tryzhdrtype'

    /usr/share/arduino/hardware/arduino/avr/cores/arduino/HardwareSerial.h:128: multiple definition of `rzfile()'
    zmodem_rz.cpp.o:/usr/share/arduino/hardware/arduino/avr/cores/arduino/HardwareSerial.h:128: first defined here
    zmodem/zmodem_rz.cpp.o: In function `getfree()':
    /usr/share/arduino/hardware/arduino/avr/cores/arduino/HardwareSerial.h:128: multiple definition of `rzfiles()'
    zmodem_rz.cpp.o:/usr/share/arduino/hardware/arduino/avr/cores/arduino/HardwareSerial.h:128: first defined here
    zmodem/zmodem_rz.cpp.o: In function `getfree()':
    /usr/share/arduino/hardware/arduino/avr/cores/arduino/HardwareSerial.h:128: multiple definition of `wcreceive(int, char**)'
    zmodem_rz.cpp.o:/usr/share/arduino/hardware/arduino/avr/cores/arduino/HardwareSerial.h:128: first defined here
    collect2: error: ld returned 1 exit status
    Error compiling.

  16. #41
    Junior Member
    Join Date
    Feb 2016
    Posts
    18
    I used Arduino IDE 1.6.5 to build the sketch and tried 1.6.7 over the weekend which worked as well.

    It looks like you have a similar issue to one I ran into when I created a "backup" directory inside my zmodem directory and then copied all the source files in there. It started giving me multiple definition errors for everything at that point.

    From the errors you are getting, it looks like you have a primary zmodem directory where you have all the source files, then a subdirectory, again called zmodem, under that with all the source files duplicated there. Get rid of the subdirectory and try compiling again.

  17. #42
    Member
    Join Date
    Jan 2016
    Location
    USA
    Posts
    46
    That's a good idea but from looking at the error messages you may have code in zmodem and its associated modules which duplicates definitions in /usr/share/arduino/hardware/arduino/avr/cores/arduino/HardwareSerial.h

    also could be problem having both SD and sdFAT libraries in same system.

    I'll look into this when i get time. I would think everyone would have the module listed above, so i wonder if you do.

    One last edit: You might want to see if your work will compile on a fresh installation of the Arduino IDE with only the specific libraries added which you need such as SdFat. I suspect that you may have removed some other libraries from the base installation whose presence would cause the sorts of problem I'm having.

    just an idea.

    John
    Last edited by jferguson; 03-07-2016 at 08:15 PM.

  18. #43
    Junior Member
    Join Date
    Jun 2015
    Location
    Cambridge, UK
    Posts
    5
    This code is exactly what I have been looking for. I want to be able to download files from the PC, over the USB/serial link, onto the SD card in my Teensy 3.5, for use in the application, without having to unplug the SD card and use a card reader/writer plugged into a PC USB port.

    I was thinking of writing some kind of server to run on the PC (using Python?) which would allow me to use the serial I/O for debug as normal but also to transfer files from the PC to the card. This would have taken quite a few days (weeks?) of effort.

    I have had all sorts of problems trying to get this to work.

    I am using a Teensy 3.5, 4Gb SD card, Arduino 1.8.5 and Teensyduino 1.42.

    I have found various postings in this forum about accessing the SD card for the Teensy 3.5, and have made what I believe to be the necessary modifications, however I get an error on the following line (in setup()).

    Code:
      
    if(!sd.chdir("/", true)) sd.errorHalt(F("sd.chdir"));
    I have to say that I am confused by the various libraries, and even which mode the SD card is in (SPI or SDIO). In order to get the code to compile I had to install the SdFat library from the library manager (V1.1.0).

    I have tried example sketches and they appear to show that everything can work correctly.

    SdFat-TeensySdioInfo. I see "sd" declared either as SdFatSdioEX (works very fast) or as SdFat. If understand correctly the EX library uses high speed SDIO mode and the other uses regular SPI? When USE_SDIO is set to 1 it works, when set to 0 it fails (and my fixes like changing the chip select to BUILTIN_SDCARD and/or adding #including <SD.h> all hell breaks loose. Nightmare! NOTE: now fixed thanks to the information in this thread. Note that this code does not work out of the box for the Teensy 3.5.

    SdFat-TeensySdioDemo. Uses libraries SdFatSdio and SdFatSdioEX. I am no expert with C++ and so I am confused where these libraries are defined, or even what functions they support. Compiles out of the box for the Teensy3.5 and shows a massive performance increase using the EX library.

    Code:
    SdFatSdioEX uses extended multi-block transfers without DMA.
    SdFatSdio uses a traditional DMA SDIO implementation.
    Note the difference is speed and busy yield time.
    
    Type '1' for SdFatSdioEX or '2' for SdFatSdio
    
    size,write,read
    bytes,KB/sec,KB/sec
    512,10295.69,14800.60
    1024,7454.23,15108.40
    2048,7295.42,15173.25
    4096,7528.96,15641.63
    8192,7448.75,15673.34
    16384,7499.14,15429.28
    32768,7446.88,15728.15
    
    totalMicros  11398790
    yieldMicros  938327
    yieldCalls   183
    yieldMaxUsec 29345
    kHzSdClk     40000
    Done
    Type '1' for SdFatSdioEX or '2' for SdFatSdio
    
    size,write,read
    bytes,KB/sec,KB/sec
    512,202.32,718.72
    1024,404.92,903.77
    2048,782.70,1815.35
    4096,1480.93,3654.39
    8192,2813.48,7066.20
    16384,4733.90,10335.29
    32768,7778.19,13057.83
    
    totalMicros  114902946
    yieldMicros  114311569
    yieldCalls   67040
    yieldMaxUsec 338288
    kHzSdClk     40000
    Done
    Type '1' for SdFatSdioEX or '2' for SdFatSdio
    SD-CardInfo. I have #define USE_SDIO 1 and const int chipSelect = BUILTIN_SDCARD;. I see that this uses libraries Sd2Card SdVolume and SdFile and not the SdFat libraries unless they are referenced under the hood so to speak. I'm guessing that this will use the standard SPI access and not the SDIO??? Anyway it works and shows that the card can be accessed and files seen.
    Code:
    const int chipSelect = BUILTIN_SDCARD; 
    Initializing SD card...Wiring is correct and a card is present.
    
    Card type: SDHC
    
    Volume type is FAT32
    
    Volume size (bytes): 3972005888
    Volume size (Kbytes): 3878912
    Volume size (Mbytes): 3788
    
    Files found on the card (name, date and size in bytes): 
    SYSTEM~1/     2019-03-21 20:46:22
      WPSETT~1.DAT  2019-03-21 20:46:22 12
      INDEXE~1      2019-03-21 20:46:22 76
    TEENSY~1.BIN  2000-01-01 01:00:00 8388608
    DISKMI~1.TXT  2015-11-01 16:53:10 535
    YCFCTX~1.TXT  2010-09-15 21:39:00 1694
    Again I'm confused about these libraries and where to find clear details of which functions exist and how to use them.

    So now to the ZMODEM transfer program code which I would like to use - Arduino_ZModem (downloaded from Github). I have made changes to use the SDIO for the Teensy3.5. Here is the output.
    Code:
    Arduino ZModem V2.1.2
    Transfer rate: 57600
    About to initialize SdCard
    About to change directory
    error: sd.chdir
    Here is the sketch (however another 8 files are in the same folder containing the ZMODEM code). I haven't included them as the problem appears to be SD related (but anyone wishing to help would need to download the other files from https://github.com/ecm-bitflipper/Arduino_ZModem).

    Code:
    #include "Arduino.h"
    #include <avr/pgmspace.h>
    
    #include <SPI.h>
    #include <SdFat.h>
    
    // Arghhh. These three links have disappeared!
    // See this page for the original code:
    // http://www.raspberryginger.com/jbailey/minix/html/dir_acf1a49c3b8ff2cb9205e4a19757c0d6.html
    // From: http://www.raspberryginger.com/jbailey/minix/html/zm_8c-source.html
    // docs at: http://www.raspberryginger.com/jbailey/minix/html/zm_8c.html
    // The minix files here might be the same thing:
    // http://www.cise.ufl.edu/~cop4600/cgi-bin/lxr/http/source.cgi/commands/zmodem/
    
    #include "zmodem_config.h"
    
    #include "zmodem.h"
    #include "zmodem_zm.h"
    
    // This works with Tera Term Pro Web Version 3.1.3 (2002/10/08)
    // (www.ayera.com) but TeraTerm only works on COM1, 2, 3 or 4.
    
    // It DOES NOT handle interruptions of the Tx or Rx lines so it
    // will NOT work in a hostile environment.
     
    /*
      Originally was an example by fat16lib of reading a directory
      and listing its files by directory entry number.
    See: http://forum.arduino.cc/index.php?topic=173562.0
    
      Heavily modified by Pete (El Supremo) to recursively list the files
      starting at a specified point in the directory structure and then
      use zmodem to transmit them to the PC via the ZSERIAL port
    
      Further heavy modifications by Dylan (monte_carlo_ecm, bitflipper, etc.)
      to create a user driven "file manager" of sorts.
      Many thanks to Pete (El Supremo) who got this started.  Much work remained
      to get receive (rz) working, mostly due to the need for speed because of the
      very small (64 bytes) Serial buffer in the Arduino.
    
      I have tested this with an Arduino Mega 2560 R3 interfacing with Windows 10
      using Hyperterminal, Syncterm and TeraTerm.  All of them seem to work, though
      their crash recovery (partial file transfer restart) behaviours vary.
      Syncterm kicks out a couple of non-fatal errors at the beginning of sending
      a file to the Arduino, but appears to always recover and complete the transfer.
    
      This sketch should work on any board with at least 30K of flash and 2K of RAM.
      Go to zmodem_config.h and disable some of the ARDUINO_SMALL_MEMORY_* macros
      for maximum peace of mind and stability if you don't need all the features
      (send, receive and file management).
    
    V2.1.2
    2018-05-11
      - Fixes for Arduino IDE 1.8.5
      - Attempted to patch for use on Teensy
    
    V2.1
    2015-03-06
      - Large scale code clean-up, reduction of variable sizes where they were
        unnecessarily large, sharing variables previously unshared between sz and
        rz, and creative use of the send/receive buffer allowed this sketch to
        BARELY fit and run with all features enabled on a board with 30K flash and
        2K of RAM.  Uno & Nano users - enjoy.
      - Some boards were unstable at baud rates above 9600.  I tracked this back
        to overrunning the SERIAL_TX_BUFFER_SIZE to my surprise.  Added a check
        if a flush() is required both in the help and directory listings, as well
        as the sendline() macro.
    
    V2.0
    2015-02-23
      - Taken over by Dylan (monte_carlo_ecm, bitflipper, etc.)
      - Added Serial based user interface
      - Added support for SparkFun MP3 shield based SDCard (see zmodem_config.h)
      - Moved CRC tables to PROGMEM to lighten footprint on dynamic memory (zmodem_crc16.cpp)
      - Added ZRQINIT at start of sz.  All terminal applications I tested didn't strictly need it, but it's
        super handy for getting the terminal application to auto start the download
      - Completed adaptation of rz to Arduino
      - Removed directory recursion for sz in favour of single file or entire current directory ("*") for sz
      - Optimized zdlread, readline, zsendline and sendline
          into macros for rz speed - still only up to 57600 baud
      - Enabled "crash recovery" for both sz and rz.  Various terminal applications may respond differently
          to restarting partially completed transfers; experiment with yours to see how it behaves.  This
          feature could be particularly useful if you have an ever growing log file and you just need to
          download the entries since your last download from your Arduino to your computer.
    
    V1.03
    140913
      - remove extraneous code such as the entire main() function
        in sz and rz and anything dependent on the vax, etc.
      - moved purgeline, sendline, readline and bttyout from rz to zm
        so that the the zmodem_rz.cpp file is not required when compiling
        sz 
        
    V1.02
    140912
      - yup, sz transfer still works.
        10 files -- 2853852 bytes
        Time = 265 secs
        
    V1.01
    140912
    This was originally working on a T++2 and now works on T3
      - This works on a T3 using the RTC/GPS/uSD breadboard
        It sent multiple files - see info.h
      - both rz and sz sources compile together here but have not
        yet ensured that transmit still works.
        
    V1.00
    130630
      - it compiles. It even times out. But it doesn't send anything
        to the PC - the TTYUSB LEDs don't blink at all
      - ARGHH. It does help to open the Serial1 port!!
      - but now it sends something to TTerm but TTerm must be answering
        with a NAK because they just repeat the same thing over
        and over again.
    
    V2.00
    130702
      - IT SENT A FILE!!!!
        It should have sent two, but I'll take it!
      - tried sending 2012/09 at 115200 - it sent the first file (138kB!)
        but hangs when it starts on the second one. The file is created
        but is zero length.
        
      - THIS VERSION SENDS MULTIPLE FILES
    
    */
    
    // Set USE_SDIO to zero for SPI card access. 
    #define USE_SDIO 1
    /*
     * SD chip select pin.  Common values are:
     *
     * Arduino Ethernet shield, pin 4.
     * SparkFun SD shield, pin 8.
     * Adafruit SD shields and modules, pin 10.
     * Default SD chip select is the SPI SS pin.
     */
    const uint8_t SD_CHIP_SELECT = SS;
      
    /////////////////////////////////////////////////////////////////
    // SdFatSdioEX uses extended multi-block transfers without DMA //
    // SdFatSdio uses a traditional DMA SDIO implementation        //
    /////////////////////////////////////////////////////////////////
    #if USE_SDIO
    // Use faster SdioCardEX
    SdFatSdioEX sd;
    // SdFatSdio sd;
    #else 
    SdFatSdio   sd;
    #endif 
    
    #define error(s) sd.errorHalt(s)
    
    // Teensy 2.0 has the LED on pin 11
    // Teensy++ 2.0 has the LED on pin 6
    // Teensy 3.x / Teensy LC have the LED on pin 13
    const int ledPin = 13;
    
    extern int Filesleft;
    extern long Totalleft;
    
    extern SdFile fout;
    //------------------------------------------------------------------------------
    // store error strings in flash
    #define sdErrorMsg(msg) sd.errorPrint(F(msg));
    //------------------------------------------------------------------------------
    
    // Dylan (monte_carlo_ecm, bitflipper, etc.) - This function was added because I found
    // that SERIAL_TX_BUFFER_SIZE was getting overrun at higher baud rates.  This modified
    // Serial.print() function ensures we are not overrunning the buffer by flushing if
    // it gets more than half full.
    
    size_t DSERIALprint(const __FlashStringHelper *ifsh)
    {
      PGM_P p = reinterpret_cast<PGM_P>(ifsh);
      size_t n = 0;
      while (1) {
        unsigned char c = pgm_read_byte(p++);
        if (c == 0) break;
        if (DSERIAL.availableForWrite() > SERIAL_TX_BUFFER_SIZE / 2) DSERIAL.flush();
        if (DSERIAL.write(c)) n++;
        else break;
      }
      return n;
    }
    
    #define DSERIALprintln(_p) ({ DSERIALprint(_p); DSERIAL.write("\r\n"); })
    
    void help(void)
    {
      DSERIALprint(Progname);
      DSERIALprint(F(" - Transfer rate: "));
      DSERIAL.flush(); DSERIAL.println(ZMODEM_SPEED); DSERIAL.flush();
      DSERIALprintln(F("Available Commands:")); DSERIAL.flush();
      DSERIALprintln(F("HELP     - Print this list of commands")); DSERIAL.flush();
      DSERIALprintln(F("DIR      - List files in current working directory - alternate LS")); DSERIAL.flush();
      DSERIALprintln(F("PWD      - Print current working directory")); DSERIAL.flush();
      DSERIALprintln(F("CD       - Change current working directory")); DSERIAL.flush();
    #ifdef ARDUINO_SMALL_MEMORY_INCLUDE_FILE_MGR
      DSERIALprintln(F("DEL file - Delete file - alternate RM")); DSERIAL.flush();
      DSERIALprintln(F("MD  dir  - Create dir - alternate MKDIR")); DSERIAL.flush();
      DSERIALprintln(F("RD  dir  - Delete dir - alternate RMDIR")); DSERIAL.flush();
    #endif
    #ifdef ARDUINO_SMALL_MEMORY_INCLUDE_SZ
      DSERIALprintln(F("SZ  file - Send file from Arduino to terminal (* = all files)")); DSERIAL.flush();
    #endif
    #ifdef ARDUINO_SMALL_MEMORY_INCLUDE_RZ  
      DSERIALprintln(F("RZ       - Receive a file from terminal to Arduino (Hyperterminal sends this")); DSERIAL.flush();
      DSERIALprintln(F("              automatically when you select Transfer->Send File...)")); DSERIAL.flush();
    #endif
    }
    
    SdFile fout;
    //dir_t *dir ;
    
    // Dylan (monte_carlo_ecm, bitflipper, etc.) - The way I made this sketch in any way operate on
    // a board with only 2K of RAM is to borrow the SZ/RZ buffer for the buffers needed by the main
    // loop(), in particular the file name parameter and the SdFat directory entry.  This is very
    // unorthodox, but now it works on an Uno.  Please see notes in zmodem_config.h for limitations
    
    #define name (&oneKbuf[512])
    #define dir ((dir_t *)&oneKbuf[256])
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    void setup()
    {
      
      // initialize the digital pin as an output.
      pinMode(ledPin, OUTPUT);
      digitalWrite(ledPin, HIGH);   // set the LED on
      delay(2000);
    
    // NOTE: The following line needs to be uncommented if DSERIAL and ZSERIAL are decoupled again for debugging
      DSERIAL.begin(9600);
      while (!DSERIAL) {
        ; // wait for serial port to connect. Needed for native USB port only
      }
      DSERIALprintln(Progname);
      DSERIALprint(F("Transfer rate: "));
      DSERIAL.println(ZMODEM_SPEED,DEC);
    
      ZSERIAL.begin(ZMODEM_SPEED);
      ZSERIAL.setTimeout(TYPICAL_SERIAL_TIMEOUT);
    
      //Initialize the SdCard.
      DSERIALprintln(F("About to initialize SdCard"));
      if (!sd.cardBegin()) {
        sdErrorMsg("\nsd.cardBegin failed");
        return;
      }
    
      DSERIALprintln(F("About to change directory"));
      sd.chvol();
      if(!sd.chdir("/", true)) sd.errorHalt(F("sd.chdir"));
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ hangs here.
    /////////////////////////////////////////////////////////////////////
    
    
      DSERIALprintln(F("SdCard setup complete"));
    
      digitalWrite(ledPin, LOW);   // set the LED on
      while (1);
    
      sd.vwd()->rewind();
    
      help();
     
    }
    
    int count_files(int *file_count, long *byte_count)
    {
      *file_count = 0;
      *byte_count = 0;
      
      sd.vwd()->rewind();
    
      while (sd.vwd()->readDir(dir) == sizeof(*dir)) {
        // read next directory entry in current working directory
    
        // format file name
        SdFile::dirName(dir, name);
    
        // remember position in directory
        uint32_t pos = sd.vwd()->curPosition();
         
        // open file
        if (!fout.open(name, O_READ)) error(F("file.open failed"));
        
        // restore root position
        else if (!sd.vwd()->seekSet(pos)) error(F("seekSet failed"));
      
        else if (!fout.isDir()) {
          *file_count = *file_count + 1;
          *byte_count = *byte_count + fout.fileSize();
        }
         
        fout.close();
      }
      return 0;
    }
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    void loop(void)
    {
      char *cmd = oneKbuf;
      char *param;
    
      digitalWrite(ledPin, HIGH);   // set the LED on
      delay(500);                  // wait for a second
      digitalWrite(ledPin, LOW);    // set the LED off
      delay(3000);                  // wait for a second
    
      *cmd = 0;
      while (DSERIAL.available()) DSERIAL.read();
      
      char c = 0;
      while(1) {
        if (DSERIAL.available() > 0) {
          c = DSERIAL.read();
          if ((c == 8 or c == 127) && strlen(cmd) > 0) cmd[strlen(cmd)-1] = 0;
          if (c == '\n' || c == '\r') break;
          DSERIAL.write(c);
          if (c != 8 && c != 127) strncat(cmd, &c, 1);
        } else {
          // Dylan (monte_carlo_ecm, bitflipper, etc.) -
          // This delay is required because I found that if I hard loop with DSERIAL.available,
          // in certain circumstances the Arduino never sees a new character.  Various forum posts
          // seem to confirm that a short delay is required when using this style of reading
          // from Serial
          delay(20);
        }
      }
       
      param = strchr(cmd, 32);
      if (param > 0) {
        *param = 0;
        param = param + 1;
      } else {
        param = &cmd[strlen(cmd)];
      }
    
      strupr(cmd);
      DSERIAL.println();
    //  DSERIALprintln(command);
    //  DSERIALprintln(parameter);
    
      if (!strcmp_P(cmd, PSTR("HELP"))) {
        
        help();
        
      } else if (!strcmp_P(cmd, PSTR("DIR")) || !strcmp_P(cmd, PSTR("LS"))) {
        DSERIALprintln(F("Directory Listing:"));
    
        sd.vwd()->rewind();
    
        while (sd.vwd()->readDir(dir) == sizeof(*dir)) {
          // read next directory entry in current working directory
      
          // format file name
          SdFile::dirName(dir, name);
    
          DSERIAL.flush(); DSERIAL.print(name); DSERIAL.flush();
          for (uint8_t i = 0; i < 16 - strlen(name); ++i) DSERIALprint(F(" "));
          if (!(dir->attributes & DIR_ATT_DIRECTORY)) {
            ultoa(dir->fileSize, name, 10);
            DSERIAL.flush(); DSERIAL.println(name); DSERIAL.flush();
          } else {
            DSERIALprintln(F("DIR"));
          }
          DSERIAL.flush();
        }
        DSERIALprintln(F("End of Directory"));
     
      } else if (!strcmp_P(cmd, PSTR("PWD"))) {
        sd.vwd()->getName(name, 13);
        DSERIALprint(F("Current working directory is "));
        DSERIAL.flush(); DSERIAL.println(name); DSERIAL.flush();
      
      } else if (!strcmp_P(cmd, PSTR("CD"))) {
        if(!sd.chdir(param, true)) {
          DSERIALprint(F("Directory "));
          DSERIAL.flush(); DSERIAL.print(param); DSERIAL.flush();
          DSERIALprintln(F(" not found"));
        } else {
          DSERIALprint(F("Current directory changed to "));
          DSERIAL.flush(); DSERIAL.println(param); DSERIAL.flush();
        }
    #ifdef ARDUINO_SMALL_MEMORY_INCLUDE_FILE_MGR
      } else if (!strcmp_P(cmd, PSTR("DEL")) || !strcmp_P(cmd, PSTR("RM"))) {
        if (!sd.remove(param)) {
          DSERIALprint(F("Failed to delete file "));
          DSERIAL.flush(); DSERIAL.println(param); DSERIAL.flush();
        } else {
          DSERIALprint(F("File "));
          DSERIAL.flush(); DSERIAL.print(param); DSERIAL.flush();
          DSERIALprintln(F(" deleted"));
        }
      } else if (!strcmp_P(cmd, PSTR("MD")) || !strcmp_P(cmd, PSTR("MKDIR"))) {
        if (!sd.mkdir(param, true)) {
          DSERIALprint(F("Failed to create directory "));
          DSERIAL.flush(); DSERIAL.println(param); DSERIAL.flush();
        } else {
          DSERIALprint(F("Directory "));
          DSERIAL.flush(); DSERIAL.print(param); DSERIAL.flush();
          DSERIALprintln(F(" created"));
        }
      } else if (!strcmp_P(cmd, PSTR("RD")) || !strcmp_P(cmd, PSTR("RMDIR"))) {
        if (!sd.rmdir(param)) {
          DSERIALprint(F("Failed to remove directory "));
          DSERIAL.flush(); DSERIAL.println(param); DSERIAL.flush();
        } else {
          DSERIALprint(F("Directory "));
          DSERIAL.flush(); DSERIAL.print(param); DSERIAL.flush();
          DSERIALprintln(F(" removed"));
        }
    #endif
    #ifdef ARDUINO_SMALL_MEMORY_INCLUDE_SZ
      } else if (!strcmp_P(cmd, PSTR("SZ"))) {
    //    Filcnt = 0;
        if (!strcmp_P(param, PSTR("*"))) {
          count_files(&Filesleft, &Totalleft);
          sd.vwd()->rewind();
    
          if (Filesleft > 0) {
            ZSERIAL.print(F("rz\r"));
            sendzrqinit();
            delay(200);
            
            while (sd.vwd()->readDir(dir) == sizeof(*dir)) {
              // read next directory entry in current working directory
          
              // format file name
              SdFile::dirName(dir, name);
                         
              // open file
              if (!fout.open(name, O_READ)) error(F("file.open failed"));
            
              else if (!fout.isDir()) {
                if (wcs(name) == ERROR) {
                  delay(500);
                  fout.close();
                  break;
                }
                else delay(500);
              }
               
              fout.close();
            }
            saybibi();
          } else {
            DSERIALprintln(F("No files found to send"));
          }
        } else if (!fout.open(param, O_READ)) {
          DSERIALprintln(F("file.open failed"));
        } else {
          // Start the ZMODEM transfer
          Filesleft = 1;
          Totalleft = fout.fileSize();
          ZSERIAL.print(F("rz\r"));
          sendzrqinit();
          delay(200);
          wcs(param);
          saybibi();
          fout.close();
        }
    #endif
    #ifdef ARDUINO_SMALL_MEMORY_INCLUDE_RZ
      } else if (!strcmp_P(cmd, PSTR("RZ"))) {
    //    DSERIALprintln(F("Receiving file..."));
        if (wcreceive(0, 0)) {
          DSERIALprintln(F("zmodem transfer failed"));
        } else {
          DSERIALprintln(F("zmodem transfer successful"));
        }
        fout.flush();
        fout.sync();
        fout.close();
    #endif
      }
    }
    So from the various example sketches I can see that the SD card can be accessed and files can be seen (albeit using different libraries - hence my confusion as to how to fix the problem).

    The first card operation to change directories fails, and it's game over. I am baffled as to what needs to be fixed.

    --Gary
    Last edited by badsector; 03-23-2019 at 01:40 PM. Reason: Using -> broke the HTML???

  19. #44
    Junior Member
    Join Date
    Feb 2016
    Posts
    18
    I wish I could help you out Gary. There are so many varieties of Arduinos out there that require different libraries. I adapted the code to work with Mega and Uno. It looks like you are very close to making it work. I do hope you eventually crack the puzzle!

  20. #45
    Junior Member
    Join Date
    Jun 2015
    Location
    Cambridge, UK
    Posts
    5
    Quote Originally Posted by bitflipper View Post
    I wish I could help you out Gary. There are so many varieties of Arduinos out there that require different libraries. I adapted the code to work with Mega and Uno. It looks like you are very close to making it work. I do hope you eventually crack the puzzle!
    After much head scratching I finally got there. I am attaching the file in case it of use to anybody else. Errr, apparently I cannot do this. I'll have to figure out where to upload the ZIP file to in order to point to it in a future post.

    I am now really pleased with the result. The serial text data and ZMODEM data share the same serial port, which makes life easier. I am using TeraTerm and I can upload and download files from/to the PC. In my application I use an external 68000 assembler tool to assemble some 68000 monitor code to a file I call "rom.bin". I then use the ZMODEM part of the sketch to download the latest assembled binary file from the PC to the SD card inside the Teesny3.5. I then hit a single key which my sketch interprets as "read rom.bin and download the contents to the 68000 board". Not having to mess around with removing the SD card is a real time saver.

    Apologies. I cannot remember all the changes or to which files (in the end the changes were fairly minor). So download the ZIP (once I point to it!) , unzip and compare against the originals.

    In my sketch use the TAB key to enter a textual command, such as "help" or "rz rom.bin", after the ">" appears. At all other times only single character keypresses are interpreted. I have left all my 68000 stuff in there, so this will need to be stripped out and replaced with your own Teensy3.5 code.

    --Gary

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •