« Close

Datasheets and User Guides

App Notes

Software & Driver

 

21.0 SD Card

Overview

The T7-Pro ships with a 2-4GB microSD card installed (SLC technology).  It might also be referred to as uSD, µSD, or just SD.  The T7 does not have the microSD card installed, but does have the card holder installed so a compatible microSD card can be installed in the field.  The retainer opens by sliding the metal piece forward, then lifting.

Currently microSDXC is not supported. Generally speaking, anything above 2GB is 'HC' meaning high capacity, and HC cards might need to be reformatted before they work.

The T7 supports FAT and FAT32 file systems, but some makes and sizes behave differently.  We recommend the following SD card format:

File System: FAT
Allocation unit size: 64 kilobytes

FAT32 with an allocation unit size of 16kb or 32kb sometimes works, but smaller allocation sizes generally do not.  On 2GB cards it's possible to select FAT format with a 32kb allocation size, and that sometimes works.

Care must be taken to ensure that power is not lost during file writing or disk corruption could occur.  The rated operating temperature of the SD card is -25°C to 85°C.  For extremely low temperatures, customers can buy industrial grade SD cards, such as the AF1GUDI-OEM, from ATP Electronics, Inc.

File and directory names are limited to ASCII characters only.  Requires firmware 1.0134 or greater.

 

Standalone Data Logging

The microSD card is generally only useful for people doing standalone data logging through Lua scripting, since normal T7 operation is with a host connected and the host can store data.  Standalone logging is an advanced topic.  We provide Lua examples for logging data to the microSD, but options for retrieving the data are somewhat limited.  Standalone logging is generally limited to command-response data rates.

 

Retrieving Data from the microSD Card

It is pretty easy to write data to the microSD card in a Lua script.  At this time there are a few options for retrieving the data from the microSD:

1.  Remove (or swap) the microSD from the T7 and put it in a card reader on a computer.  Note that on non-OEM versions of the T7/T7-Pro the enclosure must be opened to access the microSD holder.

2.  Use the beta SD utility for downloading files from the SD card via USB/Ethernet/WiFi on Windows only.  Note that the microSD and WiFi share a serial bus inside the T7, so sometimes extra thought is required if using both at the same time.

3.  Use the registers described below to read data off the microSD from user-developed software.

 

Testing the microSD Card

Not all SD cards work.  If you install a new or different SD card we recommend the following tests to make sure it works.  If you have access to a windows computer we recommend downloading and running the T7uSD testing application published on the T-Series Additional Utility Applications page.

    A.  Check Kipling to make sure that the SD card is properly recognized and that the calibration status of the device is still good.

    1. Connect to the device with Kipling
    2. On the Device Info tab and make sure there is a green checkmark next to the SD Card Installed hardware option.
    3. Check to make sure the device's calibration status is still "Good".

    B. Check to make sure the SD card can be read and written.

    1. Connect to the device with Kipling.
    2. Download and run the example script titled "Log voltage to file".
    3. Exit Kipling and open the SD Utility to verify that the file was written properly.

    C.  Check to make sure the T7's calibration constants can be read from the internal flash chip.

    1. If you are on a Windows computer, use LJStreamM to try streaming an analog input register from a T7.  If you get stream errors LJME_USING_DEFAULT_CALIBRATION (203) or LJME_INVALID_VALUE (1305), the microSD card being used is likely not compatible with the T7.

 

Errors Caused by Unsupported microSD Cards

  1. A device may get stuck in its recovery firmware version and report upgrade issues because the flash chip is not responding properly.
  2. A device may report that it is using default calibration values and be unable to be used in stream mode. The device's calibration constants are read before streaming is started.
  3. A device may have issues when running Lua scripts that try to save data to the microSD card or errors may be reported by the SD Card utility indicating that a file can't be opened.

 

Accessing the microSD Card While Using WiFi

WiFi shares an internal serial bus with the SD card and Internal Flash, and at the start of joining WiFi needs about 3 seconds of uninterrupted access on this serial bus.  If a Lua script does file I/O operations during this time, then WiFi initialization will fail and the WiFi module will immediately try again.  If Lua file I/O occurs every 3 seconds or less, it is likely that WiFi will never be able to join.  A simple way to make sure WiFi can join, perhaps with a retry or 2 needed, is to only write every 5 seconds (or longer).

Use the following Lua pseudocode to write to a file once every 5 seconds, and read an analog input once every 500ms. See the "Log voltage to file" Lua examples in Kipling for an actual script example. 

 

LJ.IntervalConfig(0, 500)  --set the DAQ interval to 500ms, should divide evenly into file access interval
LJ.IntervalConfig(1, 5000)  --set the file access interval to 5 seconds

TableSize = 5000/500
data = {}
DAQcount = 0

for i=1, TableSize do
  data[i] = 0
end

while true do
  if LJ.CheckInterval(0) then --if a data point needs to be collected
    data[DAQcount] = MB.R(0, 3)--collect a new reading from AIN0
    DAQcount = DAQcount + 1
  end
  if LJ.CheckInterval(1) then --file access interval complete
    appendToFile(data)          --save the data  to a file
    DAQcount = 0
  end
end

 

 

File I/O General Info

File Paths
  • The T7 uses Unix-style file paths where the separator character is "/".
  • The root directory doesn't require a "/". For example reading a file named "test.txt" in the "tmp" folder could be done with the path: "tmp/test.txt" or "/tmp/test.txt".

 

Common File I/O Operations

Get the name of the current working directory (CWD)
  1. Write a value of 1 to FILE_IO_DIR_CURRENT. The error returned indicates whether there is a directory loaded as current. No error (0) indicates a valid directory.
  2. Read  FILE_IO_NAME_READ_LEN.
  3. Read an array of size FILE_IO_NAME_READ_LEN from FILE_IO_NAME_READ.
  4. Resultant string will be something like "/" for the root directory, or "/DIR1/DIR2" for a directory.
Get list of items in the CWD
  1. Write a value of 1 to FILE_IO_DIR_FIRST. The error returned indicates whether anything was found. No error (0) indicates that something was found. FILE_IO_NOT_FOUND (2960) indicates that nothing was found.
  2. Read FILE_IO_NAME_READ_LEN, FILE_IO_ATTRIBUTES, and FILE_IO_SIZE. Store the attributes and size associated with each file.
  3. Read an array from FILE_IO_NAME_READ of size FILE_IO_NAME_READ_LEN. This is the name of the file/folder.
  4. Write a value of 1 to FILE_IO_DIR_NEXT. The error returned indicates whether anything was found. No error (0) indicates that there are more items->go back to step 2. FILE_IO_INVALID_OBJECT (2809) and potentially error code FILE_IO_NOT_FOUND (2960) indicates that there are no more items->Done.
Change the CWD
  1. Find from the list of items a directory to open, e.g. "/DIR1".  Directories can be parsed out of the list of items by analyzing their FILE_IO_ATTRIBUTES bitmask.  If bit 4 of the FILE_IO_ATTRIBUTES bitmask is set, then the item is a directory. 
  2. Write the directory name length in bytes to FILE_IO_NAME_WRITE_LEN (ASCII, so each char is 1 byte, also don't forget to add 1 for the null terminator).
  3. Write the directory string (converted to an array of bytes, with null terminator) to FILE_IO_NAME_WRITE.  (array size = length from step 2)
  4. Write a value of 1 to FILE_IO_DIR_CHANGE.
  5. Done.  Optionally get a list of items in the new CWD.
Get disk size and free space
  1. Read FILE_IO_DISK_SECTOR_SIZE, FILE_IO_DISK_SECTORS_PER_CLUSTER, FILE_IO_DISK_TOTAL_CLUSTERS, FILE_IO_DISK_FREE_CLUSTERS. All disk parameters are captured when you read FILE_IO_DISK_SECTOR_SIZE.
  2. Total size = SECTOR_SIZE * SECTORS_PER_CLUSTER * TOTAL_CLUSTERS. 
  3. Free size = SECTOR_SIZE * SECTORS_PER_CLUSTER * FREE_CLUSTERS.
Get disk format
  1. Read FILE_IO_DISK_FORMAT_INDEX.
  2. 2=FAT, 3=FAT32
Read a file
  1. Write the length of the file name to FILE_IO_NAME_WRITE_LEN (add 1 for the null terminator)
  2. Write the name to FILE_IO_NAME_WRITE (with null terminator)
  3. Read from FILE_IO_OPEN
  4. Read file data from FILE_IO_READ (using the size from FILE_IO_SIZE)
  5. Write a value of 1 to FILE_IO_CLOSE
Write a file
  1. Modbus interface unimplemented. Users are typically expected to create files from onboard Lua scripts. Contact [email protected] if you are interested in creating files via Modbus.
Create a directory
  1. Unimplemented.  Since Lua scripts currently do not have the ability to write files anywhere except the root directory, this feature is not implemented.

 

Register Listing

 

File IO File Operations
Name Start Address Type Access
FILE_IO_OPEN 60620 UINT16 W
FILE_IO_CLOSE 60621 UINT16 W
FILE_IO_WRITE 60654 BYTE W
FILE_IO_READ 60656 BYTE R
FILE_IO_DELETE 60622 UINT16 W
FILE_IO_ATTRIBUTES 60623 UINT16 R
FILE_IO_SIZE_BYTES 60628 UINT32 R
FILE_IO_OPEN
- Address: 60620
Write any value to this register to open a file. Must first designate which file to open by writing to FILE_IO_PATH_WRITE_LEN_BYTES then FILE_IO_PATH_WRITE.
  • Data type: UINT16  (type index = 0)
  • Write-only
  • T7:
FILE_IO_CLOSE
- Address: 60621
Write any value to this register to close the open file.
  • Data type: UINT16  (type index = 0)
  • Write-only
  • T7:
FILE_IO_WRITE
- Address: 60654
Unimplemented. This register is a buffer.
  • Data type: BYTE  (type index = 99)
  • Write-only
  • This register is a Buffer Register
  • T7:
FILE_IO_READ
- Address: 60656
Read the contents of a file. Must first write to FILE_IO_OPEN. Size of the file (in bytes) determined by FILE_IO_SIZE_BYTES. This register is a buffer. Underrun behavior - throws an error.
  • Data type: BYTE  (type index = 99)
  • Read-only
  • This register is a Buffer Register
  • T7:
FILE_IO_DELETE
- Address: 60622
Write any value to this register to delete the active file. Must first designate which file to delete by writing to FILE_IO_PATH_WRITE_LEN_BYTES then FILE_IO_PATH_WRITE.
  • Data type: UINT16  (type index = 0)
  • Write-only
  • T7:
FILE_IO_ATTRIBUTES
- Address: 60623
Bitmask: Bit0: Reserved, Bit1: Reserved, Bit2: Reserved, Bit3: Reserved, Bit4: 1=Directory, Bit5: 1=File. Used to differentiate files from directories/folders.
  • Data type: UINT16  (type index = 0)
  • Read-only
  • T7:
FILE_IO_SIZE_BYTES
- Address: 60628
The size of the file in bytes. Directories have 0 size.
  • Data type: UINT32  (type index = 1)
  • Read-only
  • T7:

Read from the disk information registers to get free space and other information.

 

File IO Disk Information
Name Start Address Type Access
FILE_IO_DISK_SECTOR_SIZE_BYTES 60630 UINT32 R
FILE_IO_DISK_SECTORS_PER_CLUSTER 60632 UINT32 R
FILE_IO_DISK_TOTAL_CLUSTERS 60634 UINT32 R
FILE_IO_DISK_FREE_CLUSTERS 60636 UINT32 R
FILE_IO_DISK_FORMAT_INDEX 60638 UINT32 R
FILE_IO_DISK_SECTOR_SIZE_BYTES
- Address: 60630
The size of each sector in the SD card in bytes. In Windows this is called the Allocation Size.
  • Data type: UINT32  (type index = 1)
  • Read-only
  • T7:
FILE_IO_DISK_SECTORS_PER_CLUSTER
- Address: 60632
The number of sectors in each cluster. Captured on read of FILE_IO_DISK_SECTOR_SIZE_BYTES.
  • Data type: UINT32  (type index = 1)
  • Read-only
  • T7:
FILE_IO_DISK_TOTAL_CLUSTERS
- Address: 60634
The total number of clusters in the SD card. Captured on read of FILE_IO_DISK_SECTOR_SIZE_BYTES.
  • Data type: UINT32  (type index = 1)
  • Read-only
  • T7:
FILE_IO_DISK_FREE_CLUSTERS
- Address: 60636
Free (available) clusters in the SD card. Used to determine free space. Captured on read of FILE_IO_DISK_SECTOR_SIZE_BYTES.
  • Data type: UINT32  (type index = 1)
  • Read-only
  • T7:
FILE_IO_DISK_FORMAT_INDEX
- Address: 60638
Used to determine the format of the SD card. 0=None or Unknown, 1=FAT12, 2=FAT16(Windows FAT), 3=FAT32
  • Data type: UINT32  (type index = 1)
  • Read-only
  • T7:

The registers that are type BYTE are AAI binary.

FILE IO and Lua
Name Start Address Type Access
FILE_IO_LUA_SWITCH_FILE 60662 UINT32 R/W
FILE_IO_LUA_SWITCH_FILE
- Address: 60662
Write any value to this register to instruct Lua scripts to switch to a new file. Lua script should periodically check LJ.CheckFileFlag() to receive instruction, then call LJ.ClearFileFlag() after file switch is complete. Useful for applications that require continuous logging in a Lua script, and on-demand file access from a host.
  • Data type: UINT32  (type index = 1)
  • Readable and writable
  • T7:

 

 

2 comments

Can you give me an example of how I can use Python or C++ and the RTC to get analog readings at a certain frequency and store the data in the SD card without having the T7-Pro connected to a host computer? Sort of like a remote data-logger. Is the T7-Pro capable of doing that yet?

The ability to log data to the SD card without a host computer is available through the Lua scripting feature: http://labjack.com/support/datasheets/t7/scripting