Введение
Вопреки расхожему мнению, применение планировщиков/диспетчеров позволяет значительно ускорить разработку приложений, затратив при этом совсем немного памяти. А, как известно, время разработчика дороже последней. Средний диспетчер занимает около 1 кБ flash. Это совсем немного, учитывая те возможности, которые он предоставляет.
Сделать свои программы более организованными мне, простому любителю, хотелось достаточно давно. Я опробовал на реальных устройствах событийную систему на таблице, диспетчер ДиХальта и планировщик. Последний меньше всего мне понравился. При использовании его "как есть" он, на мой взгляд, мало пригоден для создания приложений посложнее мигания светодиодами. Но у него есть один плюс, который меня покорил. Он очень, очень простой. А значит быстрый и надежный. Поэтому его я и взял за основу.
Итак, что же, как минимум, должно быть у диспетчера для полноценного его использования? На мой взгляд необходимо следующее:
1) Возможность однократного запуска задачи;
2) Возможность циклического запуска задачи с заданным периодом;
3) Возможность однократного или циклического отложенного запуска с заданной паузой;
4) Удаление задачи.
Перечисленного вполне достаточно для реализации самых разнообразных алгоритмов. При этом, как видим, ничего лишнего нет.
Доработка планировщика
Старый планировщик умеет запускать циклические задачи отложенно (или сразу). Это уже немало. Но чтобы реализовать весь желаемый функционал, пришлось изменить практически все его функции. Теперь по порядку.
Структура задачи и очередь задач остались неизменными:
typedef struct task
{
void (*pFunc) (void); // указатель на функцию
u16 delay; // задержка перед первым запуском задачи
u16 period; // период запуска задачи
u08 run; // флаг готовности задачи к запуску
}task;
volatile static task TaskArray[MAX_TASKS]; // очередь задач
Начиная с инициализации начинаются отличия. В исходном варианте очередь очищается путем обнуления параметров задач во всей очереди. Я же ввел дополнительную переменную «хвоста» очереди и просто обнуляю ее.
inline void RTOS_Init()
{
TCCR0 |= (1<<CS01)|(1<<CS00); // прескалер - 64
TIFR = (1<<TOV0); // очищаем флаг прерывания таймера Т0
TIMSK |= (1<<TOIE0); // разрешаем прерывание по переполнению
TIMER_COUNTER = 130; // загружаем начальное зн. в счетный регистр
arrayTail = 0; // "хвост" в 0
}
Постановщик в очередь. В старом планировщике это функция AddTask. При наличии свободного места в очереди она добавляет задачу, даже если такая уже есть в списке. Мне показалось это неудобным, поэтому задача добавляется только в том случае, если ее в списке нет. В противном случае обновляются ее параметры: пауза до выполнения и период. Поэтому функция теперь называется SetTask. Это логичней.
u08 i;
if(!taskFunc) return;
for(i = 0; i < arrayTail; i++) // поиск задачи в текущем списке
{
if(TaskArray[i].pFunc == taskFunc) // если нашли, то обновляем переменные
{
DISABLE_INTERRUPT;
TaskArray[i].delay = taskDelay;
TaskArray[i].period = taskPeriod;
TaskArray[i].run = 0;
RESTORE_INTERRUPT;
return; // обновив, выходим
}
}
if (arrayTail < MAX_TASKS) // если такой задачи в списке нет
{ // и есть место,то добавляем
DISABLE_INTERRUPT;
TaskArray[arrayTail].pFunc = taskFunc;
TaskArray[arrayTail].delay = taskDelay;
TaskArray[arrayTail].period = taskPeriod;
TaskArray[arrayTail].run = 0;
arrayTail++; // увеличиваем "хвост"
RESTORE_INTERRUPT;
}
}
Следующий шаг - удаление задачи. В старом планировщике такая функция есть, но по индексу в очереди. На практике неудобно, поэтому она была изменена. Теперь задачи удаляются по имени, причем удаление происходит не смещением всех последующих задач на шаг назад, а переносом последней задачи на место удаляемой. Это гораздо быстрее.
void RTOS_DeleteTask (void (*taskFunc)(void))
{
u08 i,j;
for (i=0; i<arrayTail; i++) // проходим по списку задач
{
if(TaskArray[i].pFunc == taskFunc) // если задача в списке найдена
{
DISABLE_INTERRUPT;
if(i != (arrayTail - 1)) // переносим последнюю задачу
{ // на место удаляемой
TaskArray[i] = TaskArray[arrayTail - 1];
}
arrayTail--; // уменьшаем указатель "хвоста"
RESTORE_INTERRUPT;
return;
}
}
}
Для реализации однократного запуска была изменена функция извлечения задачи из очереди. Если подошло время выполнения (флаг Run установлен), проверяется значение периода, если он равен 0, задача просто удаляется из очереди.
void RTOS_DispatchTask()
{
u08 i;
void (*function) (void);
for (i=0; i<arrayTail; i++) // проходим по списку задач
{
if (TaskArray[i].run == 1) // если флаг на выполнение взведен,
{ // запоминаем задачу, т.к. во
function = TaskArray[i].pFunc; // время выполнения может
// измениться индекс
if(TaskArray[i].period == 0)
{ // если период равен 0
RTOS_DeleteTask(TaskArray[i].pFunc); // удаляем задачу из списка,
}
else
{
TaskArray[i].run = 0; // иначе снимаем флаг запуска
if(!TaskArray[i].delay) // если задача не изменила задержку
{ // задаем ее
TaskArray[i].delay = TaskArray[i].period-1;
} // задача для себя может сделать паузу
}
(*function)(); // выполняем задачу
}
}
Таймерная служба осталась почти без изменений, разве что очередь теперь сканируется не полностью, а только до "хвоста".
ISR(RTOS_ISR)
{
u08 i;
TIMER_COUNTER = 130; // задаем начальное значение таймера
for (i=0; i<arrayTail; i++) // проходим по списку задач
{
if (TaskArray[i].delay == 0) // если время до выполнения истекло
TaskArray[i].run = 1; // взводим флаг запуска,
else TaskArray[i].delay--; // иначе уменьшаем время
}
}
Вот все, что касается доработок старого планировщика. Теперь использовать его уже не просто удобно, а приятно. Программа становится логичной, читабельной, простой.
Теперь несколько примеров использования.
Примеры использования планировщика
1) Запуск сканирования клавиатуры 100 раз в секунду
RTOS_SetTask(KeyScan, 0, 10); // период 10 мс, неотложенный запуск
2) В паяльной станции: после включения или изменения заданной температуры одну секунду показывается заданная, затем текущая, которая обновляется 3 раза в секунду. Всего 2 строчки, смысл которых будет понятен даже не программисту.
// где-то в программе
// вывод на экран текущей температуры каждые 300 мс
RTOS_SetTask(FEN_ViewCurrentTemp, 0, 300);
...
...
FEN_TempUp()
{
...
// пауза до вывода текущей температуры 1000 мс
RTOS_SetTask(FEN_ViewCurrentTemp, 1000, 300);
// отображение заданной температуры (1 раз)
RTOS_SetTask(FEN_ViewTargetTemp, 0, 0);
...
}
3) Зажигаем светодиод на 5 секунд:
RTOS_SetTask(LED_ON, 0, 0); // зажигаем
RTOS_SetTask(LED_OFF, 5000, 0); // гасим через 5 секунд
4) Смена цвета моргания светодиода при смене режима работы:
// где-то в программе
mode = GREEN; // установили режим
RTOS_SetTask(Blink_green, 0, 500); // задали цвет моргания
// изменение режима
mode = RED;
RTOS_DeleteTask(Blink_green); // выключили зеленый цвет моргания
RTOS_SetTask(Blink_red, 0, 500); // задали красный цвет моргания
Файлы
Автор статьи: Владимир Шибанов.
Comments
А то любит, не любит. Мы что тут, на ромашке гадаем?
Ну и удивился формулировке "не любит". И наличие команд sbi cbi. Делать новый проект, чтобы убедиться, какие команды будут подставлены мне лениво. Все равно я для этих регистров делаю прямую запись. Нули-то все равно бесполезно пихать, не так ли? В крайнем случаю лишний раз гляну в даташит, чтобы уточнить как запустить периферию.
2 - Сама ваша формулировка "МК не любит, видите ли |=" А с чего вы взяли, что будут обязательно команды sbi, cbi ?!
А то МК не любит... Не "не любит"!!! Это формулировка начинающего любителя, который не знает чего ждать от МК и программы...
1. Остановить таймер.
2. Задать в регистрах режим работы таймера (для AVR это TCCRA, TCCRC, если они есть. А если нет - то пропустить этот шаг). Причем делать это явным присваиванием (а не пресловутой операцией |= ). Регистр, где запускается таймер - не трогать.
3. Инициализовать счетный регистр TCNTn.
4. Инициализовать регистр(ы) сравнения OCCRn
5. В регистре TIFR cбросить флаги относящиеся к таймеру-пОциенту.
6. Разрешить нужные прерывания таймера, запрещая ненужные.
7. Запустить таймер, одновременно до-задавая режим его работы - для AVR это TCCRnB(если он есть) или TCCRn. Причем тоже операцией простого присваивания, а не |=.
После такой процедуры таймер не подведет.
Готов обсудить.
Массив из нужного кол-ва таймеров. Структура массива: статусный байт, 16-битный счетчик. Прерывание настроено на 1 мс. В обработчике прерывания только перезапуск таймера, для точного отбивания по 1 мс. И установка флага. В основной программе вызывается Service_Timers. Зашли, проверили флаг, не установлен, вышли. Установлен, пробежались по массиву, если в статусном байте установлен флаг TMR_UNLOCK_FLG, декремент 16-битного счетчика. Обработка следующего таймера. Если флаг не установлен, обработка следующего таймера. Время вышло (0), установка флага TIME_OUT_FLG.
Но есть но: представим ситуацию. Нам нужно запустить задачу на 10 мс. И установка таймера задача произошла перед прерыванием. В итоге получится не 10 мс, а 9 с небольшим. Но так как я эти таймеры использую в задачах, где 10, даже 100 мкс погоды не играют. Абсолютно. Ну будет разброс в мкс обработки матричной клавиатуры, или обновление символьного ЖКИ. Ну и хрен на него, на это расброс.
Зато я получил простую в использовании таймерную службу. Максимальное время 65535 мс. Если мне требуются большие отрезки времени, в модулях использую дополнительные счетчики. Скажем, счет каждые 100 мс.
Дальше планирую допилить, чтобы был флаг инкремент-декре мент. И пауза таймеров. Например, это потребуется в следующих ситуациях. Есть оборудование с режимом "Пауза". Вот в этих случаях и требуется наличие паузы в таймерах.
Да, я о проблеме атомарности, если че))
На данный момент мой опыт: пока всякие диспетчеры мне ни разу не понадобились.
void main (void)
{
func_1 ();
func_2 ();
func_3 ();
}
Все! Главные принципы: модули, автоматное программировани е. Каждая задача разбивается так, чтобы не было долгих циклов. К примеру, системный тик 1 мс. И каждый пробег main должен с запасом уложиться в 1 мс.
Ну как-то так...
И не диспетчеры нужно лепить, а научиться взаимодействию модулей.
Потому что эти материалы читают начинающие. Которые вроде как нашли решение, как же, ляпаешь как попало задачи, и они блин работают. А если таким начинающим придет в голову применить эти диспетчеры и потом вляпываются по самое не балуй...
1) по поводу |=. Установка флага в регистре TIFR у меня происходит именно так, архив чуть устаревший отправил Паше. Уже попросил его поправить статью. Я не силен в ассемблере, но команда TIFR |= (1
1) по поводу |=. Установка флага в регистре TIFR у меня происходит именно так, архив чуть устаревший отправил Паше. Уже попросил его поправить статью. Я не силен в ассемблере, но команда TIFR |= (1 shl TOV0); транслируется в 3 асмкоманды: IN, ORI, OUT. Ни разу у меня не было конфликтов, связанных с установкой флага с помощью |=. Возможно потому, что в инициализациях я не разрешаю глобальные прерывания. Делаю это уже перед основным циклом.
Транслируется правильно, но сам алгоритм неправильный.
Quoting Владимир:
Видимо для ваших программ это не было важно.
Проблема может возникнуть в старых мегах - регистр TIFR зашарен между некоторыми таймерами. Поэтому в результате операции |= могут быть сброшены все флаги, а не один. В результате можно потерять прерывания или не отреагировать на нужный флаг.
И для сброса бита в TIFR достаточно записать в нужную позицию 1 - на асме это две команды:
Code:
ldi reg, 1<<BIT_POS
out TIFR, reg
Code:
TIFR = (1<<TOV0);
Без ИЛИ.
Вот на них как раз проблемы и могут быть - на более новых мегах обычно на каждый таймер выделяется свой TIFRx.
Quoting Владимир:
Code:
TIFR=1<<TOV0;
Согласен с тем, о чем Вы говорите. Про опрос флага таймера в основном цикле я не думал. Возможно кто-нибудь захочет доработать этот диспетчер, добавить функциональност и. Например было бы неплохо добавить удаление задачи из списка через заданное время. Возможно сам доработаю, но уже не для avr, а для stm. Следующий проект будет на нем и планирую переводить туда этот диспетчер.
Так вот никакого диспетчера у меня в помине нет. Main и список вызываемых функций. Все. А вы диспетчер в паяльную тсанцию засунули. Что у вас там? Кнопки, дисплей, неважно какой. Термодатчик, нагреватель паяльника. Ну управление питанием еще. Спрашивается, зачем в паяльной станции диспетчер? Лучше автоматным программировани ем бы занялись. И диспетчеры тогда вам еще не скоро понадобятся...
Еще могу добавить по автоматному программировани ю. 2 года назад я делал контроллер управления гальванической линией металлизации печатных плат, а это: 5 ванн с терморегулирова нием и контролем уровня, 3 струйных промывки, включение источников тока и барботажа, система перемещения заготовки (2 шаговых дигателя с концевиками), дисплей. Делал на автоматах. Сейчас я даже не хочу в тот код залазить. Так вот, к чему я это? А к тому, что для каждой задачи надо выбирать оптимальное решение!
pastebin.com/Qdhdh370
Когда у меня началось получаться с си, тогда я начал понимать, что мне говорили спецы на форуме.
Поэтому я и говорю, не стоит тратить время на диспетчеры, если еще не научился модульному программировани ю, автоматному программировани ю. И тогда тебе, возможно вообще не потребуются диспетчеры. RTOS - это уже иная тема...
По поводу автоматов, когда задач становится слишком много, сложно понять структуру программы. Я ничуть не умаляю достоинств такой организации, тем более диспетчер по своей сути автоматом и является. Точнее его более структурированн ым вариантом.
Quoting demiurg:
Вот с этим абсолютно согласен.
6) По поводу тестирования. Я очень долго прогонял его и в симуляторе, и в железе. И он претерпел немало доработок. Но если кому-то захочется целенаправленно его потестировать на баги - я только за!)
а) если переменная лишь читается в прерывании, то достаточно в фоновой функции обеспечить атомарность при ее изменении.
б) если переменная изменяется в прерывании - то в фоновой функции нужно обеспечивать атомарность и при ее чтении и при ее изменении
Из значительного: функция DeleteTask сначала сдвигала очередь после удаляемой задачи на одну позицию. Потом один человек подсказал идею с перестановкой только последней задачи. На тот момент функция Dispatch выглядела так:
Code:
void RTOS_DispatchTask()
{
u08 i;
for (i=0; i<arrayTail; i++)
{
if (TaskArray.run == 1)
{
(TaskArray.pFunc)();
if(TaskArray.period == 0)
{
RTOS_DeleteTask(TaskArray.pFunc);
}
else
{
TaskArray.run = 0;
if(!TaskArray.delay)
{
TaskArray.delay = TaskArray.period-1;
}
}
}
}
}
Довольно быстро проявился глюк, когда задача удаляет саму себя, установка delay происходила для другой задачи, которая вставала на место удаляемой. Поэтому функция Dispatch обрела такой вид, как в статье.
Плюсую. Диспетчер DI HALT-а сразу же так и переделал. У него в прерывании было, я вынес в основной цикл. В прерывании взводится флаг. В основном цикле проверяется флаг, если установлен, сброс флага, прочесывание очереди. Точность в единицы, десятки мкс не критична.
Я решил все-таки собрать диспетчер. Позже выложу результат.
Если использовать диспетчер, то нужно четко определить, что считать задачей? Почему-то в диспетчерах задачей считают моргалку светодиодом. Воткнули моргалку, она исправно моргает, вау! Диспетчер, задача, епт! Хорошо, а если много светодиодов? И разные световые эффекты. Как тогда быть? На автоматах легко это делается. Через диспетчер замаешься разруливать.
Вот если вытеснение, тогда уже другое дело. Простенький переключатель задач уже имеет право на существование. Но опять же, нужно четкое определение, что такое задача. Это не какая-то функция, которая запускается через определенное время.
Задача диспетчеров - распараллеливан ие задач.
Но опять же, если следовать некоторым правилам, то выясняется, что диспетчер опять не требуется.
Правила простые. Модульность. Большие функции разбиваются. Никаких долгих циклов в функциях. Зашли, выполнили код, вышли. Проверили условие, вышли. Все это делается на флагах, автоматах, какие-либо условия.
И при чем тут avr? Какая разница какая архитектура контроллера? Дело ведь не в ней, а в структурном представлении программы. Причем модульности последней никто не отменял!
На форумах иногда попадались личности, нежелающие использовать диспетчеры на avr, основываясь только на малом объеме памяти и быстродействии. Зато переходя на эти же stm первым делом изучали например freeRTOS. Только потому, что "так все делают". Появилась какая-то тенценция применения ОСРВ на ARM'ах, особенно, если присутствует мало-мальский графический интерфейс. На мой взгляд, совершенно необоснованная. Возможности диспетчеров позволяют в большинстве случаев обойтись без ОСРВ, а разница в быстродействии с автоматами измеряется микросекундами, не думаю, что сильно критично. Более того, могут быть ситуации, когда диспетчер окажется быстрее. Зависит от количества задач и частоты их запуска.
Вы недавно правильно сказали, дело в опыте.
Я мучался с диспетчером, пока меня не ткнули в автоматное программировани е. Поверьте, как только я увидел преимущество КА, сразу же выкинул диспетчер.
Quoting demiurg:
Что не устраивало Вас в том диспетчере? Когда я сформировал свои требования и реализовал их, использование диспетчера приносит только удовольствие, никаких мучений!
Quoting demiurg:
Вобще не согласен, на своем диспетчере я делал подсветку для коньков с более чем 10-ю эффектами, в большинстве из них используются переливы. При этом есть ИК-синхронизаци я между ними + пара кнопок. Очень прозрачно все написано, даже после длительного перерыва можно быстро во всем разобраться. Я не спорю, можно сделать и на автоматах. В этом случае будет даже эффективней в плане производительно сти. Но прога и так простаивает большую часть времени. А удобство восприятия программы на диспетчере с функциями SetTask(func, delay, period) мне нравится гораздо больше, чем просто список функций, непонятно как и когда вызываемых. ИМХО.
Между коньками естесственно
Так я с этим и не спорил. Даже наоборот, говорил что для каждой задачи организация программы выбирается индивидуально! Я не имею ничего против автоматов!
Ну и там много еще чего интересного.
К примеру у Татарчевского рассказано, как можно реализовать опрос клавиатуры.
Вкратце: перед вызовом автомата сканируются кнопки. В зависимости от того, какая клавиатура, пишется соответствующая функция. Матричная клавиатура, на одном порту, на нескольких портах. Дальше работает конечный автомат. Главная идея: сколько бы кнопок не было, они обрабатываются, как одна. И вам не нужно извращаться с диспетчером. Лично у меня опрос клавиатуры идет в модуле вывода информации на дисплей. Ну а если уж так приспичило использовать диспетчер, смотрите по программе, как вам запускать. Или как самостоятельную задачу, или в составе модуля.
pastebin.com/URMd767u
Идем дальше. Как дальше использовать. Отсканировали, распознали кнопки. В буфере у нас код кнопки.
У меня это сделано так:
В конечном автомате:
Code:
void Tui_Service_Main_Init (void)
{
set_menu (L_OUT_MODE);
}
void Tui_Service_Main_Out_Mode (void) { if (proc_menu_keys ()) return; // Если была обработка кнопок - выход.
Code:
key_code = 0;
SetPortKeys = 0x08;
PortKeys = 0x77;
if ((PinPortKeys&0x01)==0x00) key_code=HEAT_key;
if ((PinPortKeys&0x02)==0x00) key_code=PREV_key;
if ((PinPortKeys&0x04)==0x00) key_code=START_key;
SetPortKeys = 0x10;
PortKeys = 0x6F;
if ((PinPortKeys&0x01)==0x00) key_code=ESC_key;
if ((PinPortKeys&0x02)==0x00) key_code=SET_key;
if ((PinPortKeys&0x04)==0x00) key_code=ENTER_key;
SetPortKeys = 0x20;
PortKeys = 0x5F;
if ((PinPortKeys&0x01)==0x00) key_code=PAUSE_key;
if ((PinPortKeys&0x02)==0x00) key_code=NEXT_key;
if ((PinPortKeys&0x04)==0x00) key_code=STOP_key;
SetPortKeys = 0;
PortKeys = 0x40;
Потом в основном цикле проверял код кнопки.
В паяльной станции я сделал по другому, т.к. всего 5 кнопок.
Code:
void BUT_Scan()
{
// define | counter | short press | long press
TestButton (BUT_FEN_SET, &fenSetPressed, FEN_SetMode, FEN_Off);
TestButton (BUT_FEN_DOWN, &fenDownPressed, FEN_TempDown, NULL);
TestButton (BUT_FEN_UP, &fenUpPressed, FEN_TempUp, FEN_SaveTemp);
TestButton (BUT_SOLD_DOWN, &soldDownPressed, SOLD_TempDown, SOLD_Off);
TestButton (BUT_SOLD_UP, &soldUpPressed, SOLD_TempUp, SOLD_SaveTemp);
}
Согласитесь, приведенный фрагмент (если его выровнять, получится таблица) раскрывает весь функционал программы. К этому я и стремился.
Code:
RTOS_SetTask(BUT_Scan, 0, 10);
Остальное разрулит фрагмент, приведенный выше. А он к диспетчеру можно сказать не имеет отношения.
Как так? Что там переписывать нужно?
Если плюсы понимает, то си наверняка поймёт.
Code:
#include <rtos.h>
на
Code:
#include "rtos.h"
Code:
rtos.c: In function 'RTOS_Init':
rtos.c:15: error: 'TCCR0' undeclared (first use in this function)
rtos.c:15: error: (Each undeclared identifier is reported only once
rtos.c:15: error: for each function it appears in.)
rtos.c:16: error: 'TIFR' undeclared (first use in this function)
rtos.c:17: error: 'TIMSK' undeclared (first use in this function)
В mega328 нет таких регистров, вот и выдаёт ошибку. Там TIMSK соответствует TIMSK0, TIFR - TIFR0 и так далее.
Кому интересно -- пишите.
void RTOS_Reset()
{
arrayTail = 0; // "хвост" в 0
}
Запустил на LED матрице 8х8. Параметр ПЕРИОД очень пригодился, позволил визуально проверить последовательно сть зажигания светодиодов и работу кода.
Маленькая поправка. В коде заголовочные файлы в угловых скобках (а не кавычках), поэтому компилятор ругается. Или это только у меня?!.
И еще было бы не плохо написать процедуру запуска с одной тестовой задачей (TskTest). Легче сразу разобраться.
В свойствах проекта надо прописать корневой каталог проекта, тогда угловые скобки будут работать. Ну или переделать на кавычки.
Как пример можно посмотреть код моей станции. Там много файлов, но для начала надо смотреть ssf.c и buttons.c
Спасибо буду знать
Этот планировщик и ему подобные не имеют никакого смысла. Потому что начинающие программисты считают, что подобные планировщики и диспетчеры якобы решают их проблемы. Но на самом деле приобретают лишний геморрой.
Решение главной проблемы (взаимодействие модулей и своевременное выполнение программного кода) следующее:
Исключение долгих циклов программных модулей, дробление выполнения модулями программного кода. Программные таймеры. Автоматное программировани е. Конечные автоматы.
вполне нормально так работает...нагр евалки-мигалки аля подобное ак раз вполне это для него...
автору спасибо что делитесь своими знаниями ,и подробные объяснения по коду.
https://drive.google.com/file/d/0B6yun0FRTB-DalJhUmpFSF80Y28/view
С прикладной точки зрения все не так однозначно. Главная проблема - необходимость определять время выполнения каждой функции (знаю, в симуляторе AVR это легко). Для небольших проектов реально, но в ряде случаев это может стать проблемой.
В целом интересная утилитка. Мне понравилась.
Читал с удовольствием как саму статью так и разгоревшуюся дискуссию в комментариях
My web-site: best time to post
on social media: https://www.4shared.com/web/preview/pdf/H9p8vvU7ca?
medicine-grade, naturally produced marijuana products for
medical use with the best quality customer support
available. Some states have processes for certifying
and registering eligible folks. Some have additionally designated dispensaries, or medical marijuana facilities, the place
individuals can get the product and advice on dosing and what type
to make use of for his or her condition. Research
report that marijuana has doable profit for several conditions.
State legal guidelines range in which situations qualify individuals for treatment with medical marijuana.
If you happen to're contemplating marijuana for medical use, verify your state's regulations.
Nausea, vomiting or extreme wasting related to most cancers remedy.
If you're experiencing uncomfortable symptoms or unintended effects of medical remedy, particularly ache and nausea, speak with your physician about all your choices before attempting marijuana.
The state had nearly 10,800 registered patients as of the top of
last yr. Craig West, the dispensary operations supervisor, stated Thursday
the most important cause is that Compassionate Sciences is the
only one in the state to offer cannabis extract s to its
patients. In all probability between 20 and 30 p.c of our patients buy extracts,” he said, including that
a whole lot of sufferers journey two hours from the tippy-prime of the state” to obtain the extracts.
The primary cannabis-infuse d lozenges have been accredited for sale within the
state final October. At that time, the dispensary was selling a bottle of 30 grape- or
cherry-flavor lozenges for $75, or $60 if sufferers qualify for financial help, in response
to a discover despatched out to sufferers.
Which means the Egg Harbor-based mostly dispensary in Atlantic County is the second to the final in the state in terms
of patients and gross sales. According to the report,
about 4,seven hundred new sufferers registered for the program
final year, nearly doubling the number from the previous year.
WebMD describes spasticity as a muscle control dysfunction that
is characterised by tight or stiff muscle tissue and an incapability to manage
these muscle groups.” About 39 percent of patients who are
eligible for marijuana are recognized with this
situation. The second most common ailment was listed as severe or power pain,” based
on the Health Division report.
The brand new heart had some hiccups early Friday in the form of some laptop issues associated to the state's new customer monitoring system for ensuring patients don't exceed a
limit of 3 ounces in a 14-day period. But those hold-ups were nothing compared with the gradual
progress of Delaware's foray into medical marijuana , a point of frustration for many sufferers.
Marijuana is still unlawful below federal legislation, even for medicinal use.
But under state regulation, Delawareans can apply for a medical marijuana card to purchase cannabis at a dispensary so long as a physician has licensed that they
have sure qualifying situations, together with cancer, Alzheimer's illness, a number of sclerosis, HIV and illnesses that cause severe ache and nausea.
Legal points and construction delays pushed First State's opening in Wilmington back to mid-2015 - around the same time lawmakers
voted to decriminaliz e marijuana, downgrading possession of
1 ounce from a felony offense to a civil violation, like a parking ticket.
By then, greater than 300 Delawareans have been licensed to make use
of medical marijuana. At present, more than three,000 patients statewide are licensed to buy cannabis.
First State Compassion Middle, a new medical marijuana dispensary near Lewes.
As a substitute, the New Castle County dispensary has nearly doubled its crop production to accommodate
the Sussex County operation and growing demand close to Wilmington.
Columbia's facility is slated to open this fall, although
an exact location has not yet been disclosed. Shari Mosley, a
fifty seven-year-old Dover resident who makes use of medical marijuana to help
treat her multiple sclerosis, said she's trying
forward to with the ability to purchase cannabis nearer to residence.
The within of the Columbia Care medical marijuana dispensary is seen in New York
January 7, 2016.Shannon Stapleton. THE BIG APPLE (Reuters)
- New York state opened its first medical marijuana dispensaries on Thursday, launching one of the most conservative and tightly
monitored applications of its form within the United States.
Not like all the opposite states that permit medical marijuana except Minnesota, New
York prohibits marijuana for smoking. It permits the drug to be offered solely in liquid or oil form to be used in vaporizers and inhalers, or
capsules taken orally. In addition, New York requires a 4-hour mandatory training course for physicians before they can certify sufferers
and for pharmacists earlier than they will dispense the drug,
a requirement not mandated by different state applications, based on the National Convention of State Legislatures.
By allowing solely refined marijuana extracts, not smokable
crude plant or so-referred to as edibles, the state is
permitting for larger dosing standardization and purity,
Bednarczyk mentioned.
We're additionally proud to perpetuate the Cannabis
motion by way of our efforts in local and nationwide business and
affected person outreach programs. We strive to present the widest variety of regionally sourced and in home strains for our sufferers.
Signal up to obtain the most recent news and deals from The Clinic Nevada!
Nonetheless, we're too busy swooning over the plush interiors of America's rising dispensary architecture to care about any of those things.
The rising authorized marijuana industry is the quickest-growin g trade in the United States.
Indeed, there are even structure and design corporations that
specialize in the design of dispensaries and develop rooms.
Jensen stated the durability and security
of a financial institution added to the constructing's enchantment as a house for the
potential dispensary. Jensen, an lawyer turned entrepreneur who has worked as a mentor with the Maryland Middle for Entrepreneurshi p, Howard County's business incubator, mentioned his experience as a most
cancers survivor was one thing that led him to the medical cannabis
trade, which is simply getting its begin within the state.
The business' team also contains Melanie Galloway, the previous director of Crownsville's
Serenity Acres drug rehabilitation clinic. Evolution Wellness was certainly one of 12 businesses awarded
a dispensary license in December to function in Anne Arundel.
Rising Medical Marijuana Card Doctor and the Studio City Easy
Clinic in Valley Village additionally moved across the road to the easily accessible Starbucks shopping middle.
The Studio Metropolis Simple clinic is now at the nook of Laurel Canyon and Riverside
Dr at 12045 Riverside Dr Los Angeles CA, 91607. Open since 2009, Hollywood Easy Clinic and Medical Marijuana Card
Physician concentrate on medical hashish evaluations, recommendations , renewals, playing cards
and cultivation licenses for growing marijuana.
Cannabis in Hollywood Los Angeles has its biggest advocate with Medical Marijuana Card Physician of the Hollywood Simple Clinic.
California marijuana patients of Medical Marijuana
Card Physician on the Hollywood Simple Clinic are the best advocates for
how you can get a medical marijuana card.
You should use this advice alone to get access
to a cannabis club. However, a medical marijuana card is
offered via our clinic for $20. Solely after you might have a valid and verified medical hashish suggestion are you able to receive a
California State Verified medical marijuana identification card administered by your native
county Division of Public Well being. If you are at the moment ready over an hour at
one other docs workplace that looks just like the DMV, name and ask our cannabis clinic workers how simple
it's to get a medical cannabis card at one in every of our clinics.
These articles are thought of the California authority on medical
hashish.Medical Marijuana Card Doctor and his consulting marijuana physicians
comparable to Rising Medical Marijuana Doctor also work
at the Studio Metropolis Simple Clinic. Studio Metropolis Simple Clinic, open since 2011, serves the sufferers of Sherman Oaks, North
Hollywood, Van Nuys, Reseda. Our medical cannabis medical doctors train our
patients about the advantages of organic meals, train and pure medicine as
a complement to present medical care. Medical hashish patients as far west as Ventura County, Santa Barbara and Pismo Beach
come to see if cannabis could be a protected part of their therapy plan.
Renewals $forty five (renewal worth only counts if your suggestion hasn't expired prior to now 6 months) Full Bundle $eighty five.
Often called the California Compassionate Use Act,” Proposition 215 was
enacted by California voters and took effect on November sixth, 1996.
Marijuana Dispensaries are fashioned by these collectives or
teams of medical marijuana patients. Medical hashish in California has given energy again to the patient and made medical marijuana medical doctors objective observers to help patients in managing the advantages
of marijuana with the negative effects of marijuana.Medic al
marijuana card necessities have turn out to be higher defined because the
legalization of medical marijuana.
Alternative suggestions are $30 and includes a miniature advice so you're much less more likely to lose it
again. Medical Marijuana Card San Francisco Doctor is a local Californian with a family history of farmers from Sonoma County
in Northern California. He has worked with many different doctor's workplaces that specialize in medical marijuana and was dissatisfied
with the level of disregard for affected person nicely being.
However, he has utilized all of the greatest rules from each medical marijuana docs
office into his personal apply with the Hollywood Easy Clinic.
Hollywood Easy Clinic is a medical doctor's office that is situated in Los Angeles County, California specializing in medical
marijuana cards, evaluations, suggestions and renewals.
Our staff supplies steerage based on the affected person's needs and
most sufferers uncover sure strains that provide the very best aid for his or her individual symptoms.
Medical marijuana dispensaries are open in Nevada.
Anyone with a medical marijuana card (even from out-of-state) is allowed to possess as
much as 2.5 oz of hashish. Leisure and medical marijuana dispensaries are up and running in Nevada.
Nevada recognizes reciprocity with different medical marijuana states,
which means your medical card from out-of-state
is valid at any Nevada dispensary. The Easiest Method to Get a Medical Marijuana
Card from Medical doctors Who Care.
You'll even be issued a medical marijuana card and literature containing California's medical marijuana
legal guidelines. Your medical marijuana card
permits you access to holistic drugs all through the state, whether you
live in Downtown Los Angeles, Long Beach,
CA, Culver Metropolis, CA, South Gate, CA, Inglewood, CA, Huntington Park, CA or anywhere else.
Patients who have accomplished our medical examination with
a qualifying condition will receive a durable, plastic affected person ID card containing your
photograph, name, patient ID number, and your birthdate.
This card could also be presented to regulation enforcement and incorporates necessary information about California's medical marijuana
legal guidelines.
Also visit my blog ... marijuana clinic - www.smartmylife.fr: https://www.smartmylife.fr/smartnews/groups/california-is-the-first-state-to-cross-marijuana-legal-guidelines-to-permit-california-sufferers-to-satisfy-with-medical-doctors-in-clinic-or-online-by-way-of-tele-medicine-to-visit-with-420-docs-for/members/ -
content. Writing manually takes a lot of time, but there is tool for this boring
task, search for: Wrastain's tools for content
Feel free to surf to my homepage PatX: https://Roy2009.blogspot.com
RSS feed for comments to this post