Товары из Китая

Victor VC921 в домашней автоматизированной лаборатории


  • Цена: 8.24 евро
  • Сегодня будет суперзапоздавший обзор тестера, уже много лет валявшегося в дальнем углу абсолютно без дела. Предпримем попытку расширить нашу автоматизированную домашнюю лабораторию и подключим дешевый тестер к системе на базе Labview.

    Телега сильно забежала впереди лошади — у меня был запланирован обзор одного прибора и половина статьи, касающейся установки и использования Labview вполне легально, уже написана, а прибор еще где-то идет, и на разработку виртуальных инструментов для этого прибора и дописывания обзора понадобится еще неделя-другая после получения. Последовательность оказалось перепутана. Пояснения, если кому они нужны, будут в моем следующем обзоре.

    Для начала — хорошие обзоры на этот тестер здесь уже есть, первый и второй, повторяться не буду. Это не все — я насчитал здесь 4 обзора на этот тестер.

    Если есть много денег и большая нужда, конечно, самый простой вариант поставить на полочку штуки 2-3 старых добрых мультиметра 6.5 Hewlett-Packard HP 34401A, который вроде как Agilent сейчас кличут, парочку источников-измерителей Keithley 24xx с последними циферками по вашему вкусу, несколько программируемых источников питания — все это соединить IEEE-488 (Hewlett-Packard Interface Bus в девичестве).

    Victor VC921 в домашней автоматизированной лаборатории

    Всего этого добра не нашлось, зато нашелся Victor VC921, который я купил лет 6 тому назад за 8.24 евро на Али.

    Victor VC921 в домашней автоматизированной лаборатории

    Друг такой купил — ему он очень понравился в качестве пищалки-звонилки. Глядя на его восторг, я тоже приобрел такой же — с тех пор и валялся в дальнем углу без использования.

    Victor VC921 в домашней автоматизированной лаборатории

    С тех пор клиент уехал, гипс сняли и даже магазин больше не существует.

    Если пойдете по этой кривой дорожке — имейте в виду, что этот тестер в большинстве случаев уже не торт — внешне выглядит так же, но нутро другое.

    Вид снизу:

    Victor VC921 в домашней автоматизированной лаборатории

    и сверху:

    Victor VC921 в домашней автоматизированной лаборатории

    На правильном тестере должна быть надпись True RMS. Но написать можно что угодно, более надежный критерий — если открыть отсек с батарейками, на печатной плате должно быть видно 2 контактных площадки для кнопок.

    Victor VC921 в домашней автоматизированной лаборатории

    Хотел бы еще один для системы такой найти — но дешево уже нет. И еще бы в довесок пару тестеров с измерением тока и температуры — у Victor VC921 таких возможностей нет, из полезного для меня — только напряжение и сопротивление. Может, у кого есть на примете подходящие недорогие варианты? — но похоже, что Victor брать смысла уже нет, за такую цену, как у него сейчас, лучше уже что-то с измерением тока найти.

    Фотографировал тестер на окне — а тут кошка Рыжик отдыхает, на вид очень счастливая кошка. Обойти и не сфотографировать ее было просто невозможно.

    Victor VC921 в домашней автоматизированной лаборатории

    Тем более так беззаботна она бывает очень редко — кошка очень тяжело болеет, ветеринары ее больше трех лет назад приговорили. Несколько раз в году у нее какой-то приступ кошачьей неврологии случается — при этом она не может глотать несколько дней подряд, хотя кушать очень хочет. Если не заталкивать кусочки мяса прямо в горло — умрет от голода. На этот раз уже больше двух недель все это длится и никак кошке лучше не становится.

    Говорят, кошки могут лечить людей — но, похоже, за счет своего здоровья или жизни. Несколько лет назад я заболел и в итоге передвигался в инвалидной коляске. Потом вроде стало отпускать, и я даже стал обходиться без коляски — но в это время заболела кошка, врачи были уверены, что умрет. Но она выжила — и сейчас мы на пару с ней глотаем таблетки из одной бутылочки.

    Совпадение или мистика? Не знаю.

    Ладно, вернемся к предмету обзора. Тестер сделан на базе широко известной в узких кругах DTM0660, у которой конфигурация и калибровки хранятся в 24C02. Нужно изменить один битик, чтобы включить последовательный протокол и заодно выключить автовыключение — для работы в составе автоматизированной системы это нам даром не надь. Идея была позаимствована отсюда.

    Victor VC921 в домашней автоматизированной лаборатории

    Victor VC921 в домашней автоматизированной лаборатории

    Чтобы не извращаться с выпаиванием EEPROM, самый простой вариант — закоротить кварц резистором на несколько десятков ом, процессор успокоится и мешать делать вам свое дело не будет. Теперь одеваем прищепку на 24C02 и меняем наши битики. Не используйте чужую прошивку — калибровка, если она делалась, вещь индивидуальная и будет сбита.

    Victor VC921 в домашней автоматизированной лаборатории

    Оригинальное содержимое EEPROM:

    Victor VC921 в домашней автоматизированной лаборатории

    и модифицированное:

    Victor VC921 в домашней автоматизированной лаборатории

    После этого на 20 ноге после долгого нажатия клавиши REL появится какая-то информация.

    Victor VC921 в домашней автоматизированной лаборатории

    По наивности считал, что это будет удобоваримая посылка, которую будет легко использовать. Зря радовался — с логическим анализатором удалось определить, что это обычный последовательной интерфейс, скорость обмена 2400 бод, в пакете 15 байт и пакет посылается 10 раз в секунду.

    Victor VC921 в домашней автоматизированной лаборатории

    Пришлось рыться в интернете — но все-таки нашел, и это похоже на бред — вместо того, чтобы отправить измеренную величину, DTM0660 отправляет состояние сегментов дисплея.

    Victor VC921 в домашней автоматизированной лаборатории

    Пришлось вытаскивать Ардуину и писать декодер наоборот — изображение 7-сегментного дисплея превращать в измеряемую величину.

    Victor VC921 в домашней автоматизированной лаборатории

    Дабы мозги понапрасну не напрягать, нашел готовый алгоритм распознавания цифр с семисегментника:

    Victor VC921 в домашней автоматизированной лаборатории

    Код ниже — но это только, чтобы понять как все работает. Старался писать как можно проще, ничего не оптимизируя, чтобы алгоритм был максимально понятен.

    Дополнительная информация


    #include <Arduino.h>

    #include <SoftwareSerial.h>

    uint8_t DiplayNums[4];

    uint32_t DisplayFlags;

    // 0 - AC

    // 1 - DC

    // 2 - AUTO

    // 3 - RS232

    // 4 - minus

    // 5 - DP1

    // 6 - DP2

    // 7 - DP3

    // 8 - u

    // 9 - n

    // 10 - k

    // 11 - diode

    // 12 - m

    // 13 - %

    // 14 - M

    // 15 - beep

    // 16 - F

    // 17 - Ohm

    // 18 - Rel

    // 19 - HOLD

    // 20 - A

    // 21 - V

    // 22 - Hz

    // 23 - Low Batt

    // 24 - Far

    // 25 - Cel

    // 26 - user1

    // 27 - user2

    // 28 - AutoOff

    // 29 - Min

    // 30 - min-max

    // 31 - max

    SoftwareSerial mySerial(2, 3); // RX, TX

    void ClearDisp(void)

    {

    for (uint8_t i=0; i<4; i++) DiplayNums[i]=0;

    DisplayFlags = 0;

    }

    void Decode(uint8_t Number)

    {

    uint8_t i = Number>>4;

    if (i>0xf) return;

    Number &= 0xF;

    uint32_t lNumber = Number;

    switch (i)

    {

    case 1:

    DisplayFlags = Number;

    break;

    case 2:

    if (Number&1) DisplayFlags |= 1<<4; // minus

    if (Number&2) DiplayNums[0] |= 1<<4; // 1E

    if (Number&4) DiplayNums[0] |= 1<<5; // 1F

    if (Number&8) DiplayNums[0] |= 1<<0; // 1A

    break;

    case 3:

    if (Number&1) DiplayNums[0] |= 1<<3; // 1D

    if (Number&2) DiplayNums[0] |= 1<<2; // 1C

    if (Number&4) DiplayNums[0] |= 1<<6; // 1G

    if (Number&8) DiplayNums[0] |= 1<<1; // 1B

    break;

    case 4:

    if (Number&1) DisplayFlags |= 1<<5; // DP1

    if (Number&2) DiplayNums[1] |= 1<<4; // 2E

    if (Number&4) DiplayNums[1] |= 1<<5; // 2F

    if (Number&8) DiplayNums[1] |= 1<<0; // 2A

    break;

    case 5:

    if (Number&1) DiplayNums[1] |= 1<<3; // 2D

    if (Number&2) DiplayNums[1] |= 1<<2; // 2C

    if (Number&4) DiplayNums[1] |= 1<<6; // 2G

    if (Number&8) DiplayNums[1] |= 1<<1; // 2B

    break;

    case 6:

    if (Number&1) DisplayFlags |= 1<<6; // DP2

    if (Number&2) DiplayNums[2] |= 1<<4; // 3E

    if (Number&4) DiplayNums[2] |= 1<<5; // 3F

    if (Number&8) DiplayNums[2] |= 1<<0; // 3A

    break;

    case 7:

    if (Number&1) DiplayNums[2] |= 1<<3; // 3D

    if (Number&2) DiplayNums[2] |= 1<<2; // 3C

    if (Number&4) DiplayNums[2] |= 1<<6; // 3G

    if (Number&8) DiplayNums[2] |= 1<<1; // 3B

    break;

    case 8:

    if (Number&1) DisplayFlags |= 1<<7; // DP3

    if (Number&2) DiplayNums[3] |= 1<<4; // 4E

    if (Number&4) DiplayNums[3] |= 1<<5; // 4F

    if (Number&8) DiplayNums[3] |= 1<<0; // 4A

    break;

    case 9:

    if (Number&1) DiplayNums[3] |= 1<<3; // 4D

    if (Number&2) DiplayNums[3] |= 1<<2; // 4C

    if (Number&4) DiplayNums[3] |= 1<<6; // 4G

    if (Number&8) DiplayNums[3] |= 1<<1; // 4B

    break;

    case 0xa:

    DisplayFlags |= lNumber<<8;

    break;

    case 0xb:

    DisplayFlags |= lNumber<<12;

    break;

    case 0xc:

    DisplayFlags |= lNumber<<16;

    break;

    case 0xd:

    DisplayFlags |= lNumber<<20;

    break;

    case 0xe:

    DisplayFlags |= lNumber<<24;

    break;

    case 0xf:

    DisplayFlags |= lNumber<<28;

    break;

    default:

    break;

    }

    }

    uint16_t SegmentDecoder(void)

    {

    uint16_t Result =0;

    for(uint8_t i=0; i<4; i++)

    {

    uint8_t Number =0 ;

    Result *= 10;

    switch (DiplayNums[i])

    {

    case 0x3F:

    Number = 0;

    break;

    case 0x06:

    Number = 1;

    break;

    case 0x5B:

    Number = 2;

    break;

    case 0x4F:

    Number = 3;

    break;

    case 0x66:

    Number = 4;

    break;

    case 0x6D:

    Number = 5;

    break;

    case 0x7D:

    Number = 6;

    break;

    case 0x07:

    Number = 7;

    break;

    case 0x7F:

    Number = 8;

    break;

    case 0x6F:

    Number = 9;

    break;

    default:

    break;

    }

    Result += Number;

    }

    return Result;

    }

    float DecodeFloat(uint16_t iValue)

    {

    float fValue = iValue;

    // 4 - minus

    // 5 - DP1

    // 6 - DP2

    // 7 - DP3

    if (DisplayFlags & (1<<5)) fValue /= 1000;

    else if (DisplayFlags & (1<<6)) fValue /= 100;

    else if (DisplayFlags & (1<<7)) fValue /= 10;

    if (DisplayFlags & (1<<4)) fValue = -fValue;

    return fValue;

    }

    void build_mode(char *String)

    {

    char * Pointer;

    Pointer = String;

    for(uint8_t i=4; i<20; i++) *(Pointer++) = '


    СМОТРИ ТАКЖЕ

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *