Как стать автором
Обновить

Java ME Embedded на Raspberry Pi

Время на прочтение6 мин
Количество просмотров30K

Насколько я могу судить, на Хабре да и не только, наблюдается всплеск интереса к микроконтроллерам — устройствам на базе ARM процессоров и другим не совсем обычным железкам. Рынок отвечает симметрично. Для удовлетворения возникшего спроса появились Arduino, Biggle Board, Raspberry Pi и множество других полезных штуковин.

С начала этого года прошло всего ничего, а на Хабре появились сразу две статьи о применении Java платформы на Rasprerry Pi «Raspberry Pi и чашечку Java, пожалуйста!» и «Raspberry PI и JAVA: пристальный взгляд». Вполне естественно, что в экспериментах использовалась привычная всем Java SE, порт которой под ARM появился около двух лет назад. Мало кто знает, что Java ME не почила с миром вместе с эрой кнопочных телефонов от Nokia. Она живет полноценной жизнью в новом мире — мире встроенных систем. О применении Java ME на Raspberry Pi я и хочу сегодня рассказать.


Oracle Java ME Embedded — это полноценный Java runtime, оптимизированный для устройств с ARM архитектурой и систем с ограниченными аппаратными возможностями. Java ME показывает себя во всей красе на платформах со слабыми вычислительными мощностями и небольшими ресурсами оперативной памяти, которые работают с сетевыми сервисами. Например, такими, как беспроводные модули, модули позиционирования, «умные» счетчики ресурсов, датчики мониторинга окружающей среды, вендинг-машины, телемедицина и, конечно, «умные» дома.

Использование Oracle Java ME в ваших проектах дает ряд интересных возможностей. Во первых, главное преимущество Java — «write once, run everywhere» теперь работает и в случае встроенных устройств. Во вторых, в платформу интегрирована система управления жизненным циклом приложений и его удаленного обновления на устройстве (AMS — application management system). В третьих, вы получаете специальный API для доступа к периферии (DAAPI — Device Access API). В четвертых, бесплатные инструменты разработки, что для встроенных систем случай нечастый (Java ME SDK для NetBeans и Eclipse). А также набор интегрированных в платформу стандартных сервисов: File I/O (JSR 75), Wireless Messaging (JSR 120), Web Services (JSR 172), Security and Trust Services Subset (SATSA – JSR 177), Location (JSR 179), XML (JSR 280).


Oracle Java ME Embedded Product Stack

Как вы уже поняли, Oracle Java ME Embedded — продукт кросс-платформенный и поддерживает ряд устройств с ARM архитектурой. Текущая версия релиза Oracle Java ME 3.3 — 3.4. Платформа портирована на Cortex-M3/RTX (KEIL Evaluation Board), ARM11/Linux (Raspberry Pi Model B), ARM9/BREW MP (Qualcomm IoE development), X86/Windows (эмулятор). Выше перечислены референсные имплементации платформы, выпущенные Oracle. Возможно портирование платформы на другие устройства при возникновении таких потребностей у конечных пользователей.

Официально минимально возможная конфигурация Oracle Java ME Embedded требует всего 130 KB RAM, 350 KB ROM. Хотя, если вы придете на встречу Java User Group в Москве 30 января http://jug.msk.ru, вы будете удивлены, насколько маленькой может быть платформа, если над ней поработать напильником. Александр Мироненко alexanderVmironenko расскажет, как он «запихнул» Java в 32кб! RAM. Полная, стандартная конфигурация требует больше памяти: 700кб RAM и 2000кb ROM, что по современным меркам все равно кажется смешным.



Всем хочется, чтобы вокруг все были умными. С умными людьми приятно общаться, а в умном доме комфортно жить. Наверное, поэтому большая часть проектов с Arduido и Raspberry Pi имеют ярко выраженную направленность на прокачку скилов нашего жилища. Типичная задача — мониторинг температуры.

Для мониторинга температуры мы сначала использовали датчики с интерфейсом SPI. Но впоследствии выяснилось, что датчики с I2C гораздо дешевле. Для изготовления термометра из Raspberry Pi и Oracle Java ME Embedded 3.3 нам потребуется цифровой термодатчик Dalas Semiconductor DS1621 в корпусе DIP8. Вот здесь можно купить его за 173 рубля http://www.electronshik.ru/item/ds1621-232961.

Подключаем его к GPIO выводам нашей платы
DS1621 Raspberry GPIO pins
pin1 SDA (GPIO 2)
pin2 SCL (GPIO 3)
pin4 GND
pin8 3.3v


Если почитать Datasheet на DS1621, можно узнать, что адрес датчика на шине конфигурируется с помощью пинов 5-6-7 в нашем примере мы установим их все в 1 замкнув на питание.



Считаем, что Raspbian у вас уже стоит и он обновлен.

Для того, чтобы у нас была возможность работать с интерфейсом I2C на Raspberry Pi. Необходимо загрузить соответствующий модуль.

Добавляем две строчки в /etc/modules
i2c-bcm2708
i2c-dev

Перегружаем плату.

Устанавливаем утилиты для работы с I2C
sudo apt-get install i2c-tools


Определяем адрес нашего устройства на шине I2C
sudo  i2cdetect -y 1

Адрес нашего датчика 4f (запомним это число)

Скачиваем стабильную версию Oracle Java ME Embedded 3.3 for Raspberry Pi Model B. В версии 3.4 добавилась только поддержка платформы Qualcomm IoE. Предварительно принимаем лицензионное соглашение. http://www.oracle.com/technetwork/java/embedded/downloads/javame/index.html?ssSourceSiteId=ocomen

Копируем runtime на Raspberry и разворачиваем в удобное место.
Например в ~/JavaME/

И от root запускаем AMS (Application Management System)
sudo ~/JavaME/bin/usertest.sh

C Raspberry Pi закончили.

Устанавливаем Java ME SDK и плагин для NetBeans или Eclipse на ваш компьютер. http://www.oracle.com/technetwork/java/javame/javamobile/download/sdk/default-303768.html

Добавляем нашу Малинку в качестве устройства для развертывания мидлета.
В меню NetBeans выбираем Tools/Java ME/Device selector
В окошке Device selector нажимаем Ctrl-D и создаем новое устройство. Для этого просто прописываем адрес нашей платы жмем Далее и если все в порядке, выбираем уровень протоколирования.

Создаем проект Java ME/ Embedded application

IDE создаст для нас скелет Java ME приложения, которое наследуется от класса MIDlet и состоит из трех методов: startApp(), pauseApp() и destroyApp(boolean unconditional). Метод startApp() запустится при старте мидлета, в нем, для простоты, мы и напишем код нашего приложения.

Java ME Embedded предоставляет нам высокоуровневый API общения с переферией — DAAPI (Deveice Access API). Для работы с I2C нам нужно создать конфигурацию устройства, передать ее в фабрику PeripheralManager.open() и если все провода в порядке и Java запущена от root, мы получим экземпляр класса I2CDevice(), который даст нам возможность общаться с датчиком.

Ниже пример кода Java ME приложения, если что-то не понятно задавайте вопросы в комментариях, приходите в офис Oracle в Санкт-Петербурге или 30-го января на http://jug.msk.ru

Чтобы запустить этот код на устройстве, нажмите правую кнопку мыши на вашей вашем проекте в NetBeans, выберите Run with… и в открывшемся окне Quick Project Run выберите вашу Raspberry. Или в свойствах проекта выберите во вкладке Platform выберите в качестве Device ваше устройство, тогда NetBeans будет деплоить приложение на Rapberry Pi по умолчанию при старте проекта.

Теперь вы знаете температуру в комнате :)

Полезные ссылки:
Java ME Embedded 3.3 for Raspberry Pi
Java ME SDK 3.4
Java ME Embedded 3.3 Getting Started Guide for the Reference Platform (Raspberry Pi)
Термодатчик DS1621 Datasheet

import com.oracle.deviceaccess.PeripheralManager;
import com.oracle.deviceaccess.i2cbus.I2CDevice;
import com.oracle.deviceaccess.i2cbus.I2CDeviceConfig;
import java.io.IOException;
import javax.microedition.midlet.*;

public class IMlet extends MIDlet {

    private final int CFG_ADDRESS = 0x4f;  //Адрес датчика
    private final int FREQ = 100000;  //Частота шины из Datasheet
    private final int ADDRESS_SIZE = 7; //Размер адреса из Datasheet
    private final int BUS_ID = 1; // Внутренний идентификатор шины в Java ME Embedded из Getting Started Guide

    // Адреса регистров и значения конфигурационных параметров датчика DS1621 подробнее в Datasheet
    private final int REG_READ_TEMP = 0xAA;
    private final int RT_ADDR_SIZE = 0x01;
    private final int READ_TEMP_SIZE = 0x02;
    private final int READ_TEMP_VAL = 0x00;
    private final int REG_ACC_CONF = 0xAC;
    private final int ACC_CONF_VAL = 0x00;
    private final int REG_START_CONV = 0xEE;
    private final int REG_STOP_CONV = 0x22;

    public void startApp() {
        // Создаем конфиг
        I2CDeviceConfig config = new I2CDeviceConfig(BUS_ID, CFG_ADDRESS, ADDRESS_SIZE, FREQ);
        I2CDevice device = null;
        try {

            // Открываем устройство
            device = (I2CDevice) PeripheralManager.open(config);

            // Конфигурируем датчика на непрерывное измерение температуры
            write(device, new byte[]{(byte) REG_ACC_CONF, (byte) ACC_CONF_VAL});
            write(device, new byte[]{(byte) REG_START_CONV});

            // Читаем температуру
            byte temp[] = new byte[READ_TEMP_SIZE];
            device.read(REG_READ_TEMP, RT_ADDR_SIZE, temp, 0, READ_TEMP_SIZE);

            // Profit!
            System.out.println("Temperature is:" + temp[0]);

        } catch (Exception ex) { // Никогда так не делайте, только для Habrahabr
            ex.printStackTrace();
        } finally {
          // Закрываем устройство
        if(device != null) { 
            try {
            device.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
            // Скажем приложению, что ему нужно самоуничтожится
            notifyDestroyed();
        }
    
      
    }
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }

    private void write(I2CDevice i2c, byte[] buffer) {
        try {
            i2c.begin();
            i2c.write(buffer, 0, buffer.length);
            i2c.end();
        } catch (IOException ex) {
            System.out.println("[I2CThermometerTest] configure exception: " + ex.getMessage());
        } catch (Exception ex) {
            System.out.println("[I2CThermometerTest] Peripherial not available exception: " + ex.getMessage());
        }
    }
}
Теги:
Хабы:
+28
Комментарии39

Публикации

Изменить настройки темы

Истории

Работа

Java разработчик
352 вакансии

Ближайшие события